SynchronizationContext
WinForms と WPF の 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を対象としています