对于 WinForms 和 WPF,我将SynchronizationContext
其用作与 GUI 线程同步的一种方式。最近我遇到了旧式异步回调的问题:
private void Button_Click(object sender, RoutedEventArgs e)
{
uiContext = SynchronizationContext.Current;
var cl = new TcpClient();
cl.BeginConnect("127.0.0.1", 22222, ConnectedCallback, null);
}
public void ConnectedCallback(IAsyncResult result)
{
if (SynchronizationContext.Current != uiContext)
uiContext.Post(x => MyUIOperation(), null);
else
MyUIOperation();
}
public void MyUIOperation()
{
Title = "Connected";
}
private SynchronizationContext uiContext;
这会抛出异常,因为SynchronizationContext.Current
回调函数中的 等于捕获的,因此 UI 操作是在回调的工作线程中执行的。
在 WinForms 中使用这个完全相同的代码就像我预期的那样工作。
现在作为一种解决方法,我正在捕获当前ManagedThreadId
并在回调中进行比较。处理此问题的正确方法是什么?
更新:
我应该补充一点,我正在修改一个非常古老的现有类,该类当前使用以下构造:
if (control.InvokeRequired())
control.BeginInvoke(SomeFunction);
else
SomeFunction();
我正在尝试删除 WinForms 依赖项,而不会对此类的客户端产生太大影响。这SomeFunction()
是引发事件,所以如果我只是调用 uiContext.Send() 或 uiContext.Post() ,执行顺序会改变,因为 Post() 将始终排队调用,而 Send() 将始终阻塞。
此外,这只是一小段代码,用于显示我的问题的根源。实际上,可以从主线程调用执行 Post() 的函数。
这是针对 .NET 4.0