2014-09-03 7 views
2

을 만들어 :VB.NET 호출이 컨트롤을 호출 할 수 없습니다,하지만 핸들이 내 상황

는 클래스 1 : 방법이있다 doSomethingAndCall 새로운 스레드 에 Class2를 생성 (콜백)

Class Class1 
    public shared sub doSomethingAndCallAsync(state as object) 
    Console.WriteLine(Form1.InvokeRequired) 'output: false 
    Console.WriteLine(Form1.IsHandleCreated) 'output: false 
    Form1.Invoke(state.callback) 'throws System.InvalidOperationException 
    end sub 

    public shared sub doSomethingAndCall(callback as object) 
    System.Threading.ThreadPool.QueueUserWorkItem(AddressOf doSomethingAndCallAsync, New With {.callback = callback}) 
    end sub 
End Class 

Class Class2 
    Public Delegate Sub doSomethingDelegate() 

    Public Sub doSomething() 
    Console.WriteLine("success!") 
    End Sub 

    Public Sub Button_Click(ByVal sender As Object, ByVal e As System.EventArgs) 
    Class1.doSomethingAndCall(New doSomethingDelegate(AddressOf doSomething)) 
    End Sub 
End Class 
: Class1.doSomethingAndCall (newCallback)을 발사 버튼

가 그것과 같다 코드

(이것은 Class2.Button_Click 시작) 동적 생성 컨트롤이

예문 내가 할 행동 예외는 다음과 같습니다

호출 또는 BeginInvoke이 창 핸들이

을 생성 될 때까지 제어에 전화해서 내가 라인 4에 console.WriteLine를 볼 수 있음을 나에게 보여 할 수없는 양식은 실제로 만들어지지 않습니다. 그래서 나는이 핸들러를 추가, 지금은의 정말 혼란 스러울 : 그래서 만든 결코 파괴 것

Private Sub Form1_HandleCreated(sender As Object, e As System.EventArgs) Handles Me.HandleCreated 
     Console.WriteLine("Handle created") 'Output: Handle created, when running program 
    End Sub 

    Private Sub Form1_HandleDestroyed(sender As Object, e As System.EventArgs) Handles Me.HandleDestroyed 
     Console.WriteLine("Handle destroyed") 'Will never Output! 
    End Sub 

을하지만 난 버튼을 클릭하면 그럼에도 불구하고 avaible 아니다? - 무슨 일이 일어나고 있는지 콜백을 올바르게 호출하는 방법을 설명해 주셔서 감사합니다.

+0

무엇이 state.callback입니까? – Derek

+0

Form1 인스턴스를 사용하고 있습니까? 타입에 대해'Form1.Invoke'라고 말한 것 같습니다. 그 타입의 인스턴스가 아닙니다. – JoelC

+0

@Derek : 스레드 풀에서 작업 할 때 스레드 (객체)에 하나의 인수 만 전달할 수 있습니다. 이것은 상태입니다. 그러나 하나 이상의 인수를 전달해야한다면 다음과 같이 할 수 있습니다 : New with {.callback = callback}. 그래서 엄청난 양의 주장을 전달할 수 있습니다. 내 경우에 콜백은 doSomethingAndCallAsync에서 호출되기를 원하는 새로운 doSomethingDelegate (AddressOf doSomething)입니다. 만약 당신이나 누군가가 더 좋은 방법을 안다면 나에게 말해 주길 바란다. – MaBi

답변

4

My.Forms.Form1의 인스턴스입니다. Form1은 각 스레드마다 다를 수 있습니다. 올바른 인스턴스에 대한 핸들이 필요합니다. 당신의 Form1에 버튼을 삭제하고 다음 코드를 추가합니다

Public Class Form1 

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
     Threading.Tasks.Task.Factory.StartNew(Sub() Class1.Wrong()) 
     Threading.Tasks.Task.Factory.StartNew(Sub() Class1.Correct(Me)) 
    End Sub 

End Class 

Public Class Class1 

    Public Shared Sub Wrong() 
     Debug.WriteLine(String.Format("(Other thread, wrong) InvokeRequired={0}, IsHandleCreated={1}", Form1.InvokeRequired, Form1.IsHandleCreated)) 
    End Sub 

    Public Shared Sub Correct(instance As Form1) 
     Debug.WriteLine(String.Format("(Other thread, correct) InvokeRequired={0}, IsHandleCreated={1}", instance.InvokeRequired, instance.IsHandleCreated)) 
    End Sub 

End Class 

출력

(올바른 다른 스레드) InvokeRequired = TRUE를, IsHandleCreated = 진정한

(다른 스레드, 잘못) InvokeRequired = False, IsHandleCreated = False

+0

해결책 "pass1을 매개 변수로 전달"에 대한 감사합니다. 나를. ThreadPool.QueueUserWorkItem 대신에 Threading.Tasks.Task.Factory.StartNew (MSDN : 작업을 생성하고 시작합니다.)를 사용하는 이유가 있습니까? (MSDN : 실행 방법 대기) 현재 생각하고 있습니다. 꽤 똑같이하고있는거야, 아니면? – MaBi

+0

@MaBi 내가 '작업'을 사용하는 이유는 단순히 더 새롭고 강력한 도구이기 때문입니다. 이 게시물을 읽으세요. [ThreadPool.QueueUserWorkItem vs Task.Factory.StartNew] (http://stackoverflow.com/questions/9200573/threadpool-queueuserworkitem-vs-task-factory-startnew). CLR 팀의 ThreadPool 개발자가 이미 언급 한 내용을 반복하여 Jon (대답) 결론에 주목하십시오. * "작업은 이제 작업을 스레드 풀에 대기시키기위한 기본 방법입니다."* –

+1

덕분에 많은 감사합니다! – MaBi