さて、週末に奇妙なものを見つけました。バックグラウンド作業を実行するためにいくつかのスレッドを生成する WPF アプリがあります。これらのバックグラウンド スレッドは、作業項目を同期コンテキストに投稿します。これは、1 つのケースを除いてすべて正常に機能しています。スレッドが終了すると、ポップアップ ウィンドウを開くアクションがディスパッチャにポストされることがあります。結局、2 つのスレッドが両方とも Dispatcher にアクションを投稿すると、1 つの処理が開始され、次に Window.ShowDialog(); でポップアップ ウィンドウを開くと、現在の実行パスは一時停止し、ダイアログ ボックスからのフィードバックを待つ必要があります。しかし、ダイアログ ボックスが開くと、Dispatcher がすぐに開始され、ポストされた 2 番目のアクションの実行が開始されるという問題が発生します。これにより、2 つのコード パスが実行されます。
私が話している動作を示すために、いくつかのサンプルコードを投稿しました。2 つのアクションを投稿し、最初のアクションがダイアログ ボックスを開くと、最初のアクションが完了するまで 2 番目のアクションは実行されません。
public partial class Window1 : Window {
private SynchronizationContext syncContext;
public Window1() {
InitializeComponent();
syncContext = SynchronizationContext.Current;
}
private void Button_ClickWithout(object sender, RoutedEventArgs e) {
// Post an action on the thread pool with the syncContext
ThreadPool.QueueUserWorkItem(BackgroundCallback, syncContext);
}
private void BackgroundCallback(object data) {
var currentContext = data as SynchronizationContext;
System.Console.WriteLine("{1}: Thread {0} started", Thread.CurrentThread.ManagedThreadId, currentContext);
// Simulate work being done
Thread.Sleep(3000);
currentContext.Post(UICallback, currentContext);
System.Console.WriteLine("{1}: Thread {0} finished", Thread.CurrentThread.ManagedThreadId, currentContext);
}
private void UICallback(object data) {
System.Console.WriteLine("{1}: UI Callback started on thread {0}", Thread.CurrentThread.ManagedThreadId, data);
var popup = new Popup();
var result = popup.ShowDialog();
System.Console.WriteLine("{1}: UI Callback finished on thread {0}", Thread.CurrentThread.ManagedThreadId, data);
}
}
XAML は、Button_ClickWithout OnClick を呼び出すボタンを含む単なる Window です。ボタンを 2 回押して 3 秒間待つと、2 つのダイアログが交互にポップアップすることがわかります。最初のダイアログがポップアップし、閉じられると 2 番目のダイアログがポップアップします。
だから私の質問は: これはバグですか? または、これを軽減して、最初のアクションが Window.ShowDialog() で実行を停止したときに、一度に 1 つのアクションしか処理できないようにするにはどうすればよいですか?
ありがとう、ラウル