문제

나는 비동기 적으로 호출되는 방법이 있습니다 System.net.sockets.networkstream.beginread 완료됩니다.

 skDelegate = New AsyncCallback(AddressOf skDataReceived)
 skStream.BeginRead(skBuffer, 0, 100000, skDelegate, New Object)

해당 콜백 메소드에서는 UI 스레드와 상호 작용해야합니다.

Sub skDataReceived(ByVal result As IAsyncResult)
    CType(My.Application.OpenForms.Item("frmMain"), frmMain).refreshStats(d1, d2)
End Sub

메소드가 완료된 후에는 예외가 발생합니다. (End Sub가 실행될 때)

실행 취소 작업은 해당 세트 작업에 적용된 것과 다른 컨텍스트가 발생했습니다. 가능한 원인은 컨텍스트가 스레드에 설정되어 복귀하지 않았기 때문입니다 (취소).

그렇다면 콜백 메소드에서 UI 스레드와 어떻게 상호 작용합니까? 내가 뭘 잘못하고 있죠?

도움이 되었습니까?

해결책

FRMMAIN 객체에서 Invoke 또는 BeginVoke를 사용하여 UI 스레드에서 실행할 메시지 (대의원)를 큐를 제공해야합니다.

C#에서 내가하는 방법은 다음과 같습니다.

frmMain.Invoke(() => frmMain.refreshStats(d1, d2));

또한 이것을 확인하십시오 호출 유형 및 용도 목록.

다른 팁

트래비스가 맞습니다. Windows Forms 응용 프로그램은 단일 스레드이며 다른 스레드에서 UI에 액세스 할 수 없습니다. begininvoke를 사용하여 UI 스레드로 호출을 마샬링해야합니다.

보다 : http://msdn.microsoft.com/en-us/library/0b1bf3y3.aspx

UI 스레드가 frmmain.refreshstats 메소드를 호출해야합니다. Control.invokerequired 속성 및 Control.invoke를 사용 하여이 작업을 수행하는 방법에는 여러 가지가 있습니다.MSDN 문서).

"endasync"메소드가 메소드 호출 UI 스레드를 안전하게 만들거나 CroshendStats 메소드를 스레드 안전 (Control.inVokerequired 사용)을 확인할 수 있습니다.

endasync ui 스레드-안전은 다음과 같습니다.

Public Delegate Sub Method(Of T1, T2)(ByVal arg1 As T1, ByVal arg2 As T2)

Sub skDataReceived(ByVal result As IAsyncResult)
    Dim frmMain As Form = CType(My.Application.OpenForms.Item("frmMain"), frmMain)
    Dim d As Method(Of Object, Object)
'create a generic delegate pointing to the refreshStats method
    d = New Method(Of Object, Object)(AddressOf frmMain.refreshStats)
'invoke the delegate under the UI thread
    frmMain.Invoke(d, New Object() {d1, d2})
End Sub

또는 refreshStats 메소드 검사를 확인하여 UI 스레드에서 스스로를 호출 해야하는지 확인할 수 있습니다.

Public Delegate Sub Method(Of T1, T2)(ByVal arg1 As T1, ByVal arg2 As T2)

Sub refreshStats(ByVal d1 As Object, ByVal d2 As Object)
'check to see if current thread is the UI thread
    If (Me.InvokeRequired = True) Then
        Dim d As Method(Of Object, Object)
'create a delegate pointing to itself
        d = New Method(Of Object, Object)(AddressOf Me.refreshStats)
'then invoke itself under the UI thread
        Me.Invoke(d, New Object() {d1, d2})
    Else
        'actual code that requires UI thread safety goes here
    End If
End Sub

UI 스레드의 양식에서 상호 작용하거나 읽을 때마다 얻은 반복되는 InvalidContexTexception 오류에 대한 솔루션 (실제로 해결 방법!)을 찾았습니다.

비동기 콜백 메소드에서 UI 스레드와 상호 작용하기 전후에 실행 컨텍스트를 백업하고 복원해야했습니다. 그런 다음 예외가 표시되는 것처럼 신비하게 사라지고 속성을 읽고 쓰고, 메소드를 호출하며, 기본적으로 UI 스레드에서 원하는 모든 것을 대의원이나 호출을 사용하지 않고 비동기 콜백과 동기로 원하는 모든 것을 수행 할 수 있습니다!

이 예외는 실제로 .net framewok 자체의 낮은 수준 버그입니다. 참조 Microsoft Connect 버그 보고서, 그러나 기능적 해결 방법이 없습니다.

해결 방법 : (생산 코드)

Sub skDataReceived(ByVal result As IAsyncResult)

    // backup the context here
    Dim syncContext As SynchronizationContext = AsyncOperationManager.SynchronizationContext

    // interact with the UI thread
    CType(My.Application.OpenForms.Item("frmMain"), frmMain).refreshStats(d1, d2)

    // restore context.
    AsyncOperationManager.SynchronizationContext = syncContext
End Sub
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top