予期しないプログラムの状態を検出するためにアサートを頻繁に使用しています。アサートは、(「再試行」を押すと) 現在のアプリケーションの状態を調べることができるように、すべてのスレッドをすぐに停止する条件付きメッセージ ボックスであると考えました。
これはそうではありません!アサート メッセージが開いている間、wpf アプリケーションはイベントの処理を続けます。デバッガーに侵入すると、アサートが最初に「見た」ものと比較して状況がまったく異なる可能性があるため、それはばかげています。アサート自体を介してアサートを起動するためのチェックが変更される場合があり、メソッドを再帰的に実行することができます-複数のアサートまたはプログラムが決して正常にならない状態の結果。
私が assert-function を理解している限り、これは設計上の問題です。ダイアログは、アプリケーション自体と同じ GUI スレッドで実行されるため、独自の目的のためにメッセージを処理する必要があります。しかし、これには多くの場合、説明されている副作用があります。
そのため、呼び出されたときに実行中のすべてのスレッドを停止するという要件を満たすアサートの代替手段を探しています。回避策として、「Debugger.Break();」を使用することがあります。デバッガーなしで開始した場合、(残念ながら) 効果はありません。
問題を説明するために、最も単純化された方法でいくつかの現象を生成する次のコードを抜粋して参照してください。
public partial class MainWindow : Window
{
int _count = 0;
public MainWindow()
{
InitializeComponent();
}
private void onLoaded(object sender, RoutedEventArgs e)
{
test();
}
protected override void OnLocationChanged(EventArgs e)
{
base.OnLocationChanged(e);
}
void test()
{
++_count;
Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() =>
{
test();
}));
Trace.TraceInformation(_count.ToString());
Debug.Assert(_count != 5);
}
}
コードを実行すると、開発者スタジオの出力パネルが表示されます。数字が 5 まで上がり、アサートが発火するのがわかります。しかし、ダイアログが開いている間、数はまだ増加しています。したがって、アサートが開いている間にアサートの状態が変化します。ここで、メイン ウィンドウを確認します。まだ応答があります。「base.OnLocationChanged(e);」にブレークポイントを設定し、メイン ウィンドウを移動 => ブレーク ポイントにヒットします。ただし、コールスタックに注意してください。
MainWindow.OnLocationChanged(System.EventArgs e)
(…)
System.dll!Microsoft.Win32.SafeNativeMethods.MessageBox(System.IntPtr
System.dll!System.Diagnostics.AssertWrapper.ShowMessageBoxAssert(stri
System.dll!System.Diagnostics.DefaultTraceListener.Fail(string message, str
System.dll!System.Diagnostics.DefaultTraceListener.Fail(string message)
System.dll!System.Diagnostics.TraceInternal.Fail(string message)
System.dll!System.Diagnostics.Debug.Assert(bool condition)
MainWindow.test()
MainWindow.test.AnonymousMethod__0()
これは、アサートが開いている間に任意のコードを実行できることを明確に示しています。
したがって、既存のすべてのスレッドを停止し、独自の (スレッド) コンテキストで実行するアサートのようなメカニズムを探しています。何か案は?