我有一种方法是异步调用的 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或开始voke来加入消息(委托)以在UI线程上执行。

这就是我在C#中做的方式。

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

还要检查一下 调用类型列表及其用途.

其他提示

特拉维斯是正确的。 Windows表单应用程序是单线线程,您无法从任何其他线程访问UI。您需要使用BeginInvoke来拨打对UI线程的调用。

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

您需要让UI线程调用frmmain.refreshstats方法。使用控制和控制属性和control。MSDN文档).

您可以使用“ endasasync”方法使方法调用UI线程安全,或者具有刷新方法检查线程安全性(使用Control.invokerequired)。

Endasasync 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线程上的表单上读取属性时就会遇到的反复出现的无效Extexception错误。

在与我的异步回调方法与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