どうしてこれが動作しないのですか?デリゲート内の静的オブジェクトのロックが機能していない
private static object Lock_HandleError = new object();
public static void HandleError(Exception ex)
{
lock(Lock_HandleError)
{
//IF the UI is processing a visual tree event (such as IsVisibleChanged), it throws an exception when showing a MessageBox as described here: http://social.msdn.microsoft.com/forums/en-US/wpf/thread/44962927-006e-4629-9aa3-100357861442
//The solution is to dispatch and queue the MessageBox. We must use BeginInvoke because dispatcher processing is suspended in such cases.
Dispatcher.CurrentDispatcher.BeginInvoke((Action)delegate()
{
lock(Lock_HandleError)
{
Dispatcher.CurrentDispatcher.BeginInvoke((Action)delegate(){
HandleError(new Exception("testing purposes only"));
}, DispatcherPriority.Background);
MessageBox.Show(ex.Message, "Application Error", MessageBoxButton.OK, MessageBoxImage.Error);
//This point is not reached until the user clicks "OK"
}
}, DispatcherPriority.Background);
}
}
public void main()
{
HandleError(new Exception("The first error"));
}
上記のコードの予想される動作は1件のエラーメッセージが一度に表示されることで、ユーザが「OK」をクリックすると、Lock_HandleError
オブジェクトに派遣スレッドから解放されます、次のHandleErrorへの呼び出しを進めることができますが、私が得ているのは、 "OK"を打つことなく、エラーメッセージの無限カスケードです。
なぜこのロックが機能しないのですか?
各ロックステートメントの出入り口にブレークポイントを設定することで、デリゲートがlock()
を呼び出していることがわかり、再度「HandleError」への新しい呼び出しをディスパッチして、MessageBoxでユーザー入力を待つことを一時停止します。
一方、別のスレッドでは、HandleErrorの呼び出しが実行されますが、MessageBoxデリゲートがロックを明示的に配置していて、まだロックされていないにもかかわらず、それをリリースした。
私はマルチスレッドで傷ついていませんが、 'BeginInvoke'メソッドで' lock'を削除できないのでしょうか? – Richard
ロックを解除しても何も成立しません。ロックはそのままであるように動作します。 UIスレッドは、ユーザーがメッセージボックスで「OK」をクリックするのを待機している間、アプリケーションの他の領域からのHandleError()への追加呼び出しを処理します。停止して待機する必要があります。 – Alain
私はここでセマフォを使用して問題を解決しようとしました:http://stackoverflow.com/questions/9894750/how-can-i-get-the-ui-thread-to-wait-on-a-semaphore-but -process-additional-dispa – Alain