我经常使用断言来检测意外的程序状态。我认为断言是一个条件消息框,它会立即停止所有线程,以便(在按下“重试”时)我可以检查当前的应用程序状态。
不是这种情况!当断言消息打开时,我的 wpf 应用程序继续处理事件。这是荒谬的,因为在闯入调试器时,情况可能与断言最初“看到”的情况完全不同。您可以通过断言本身检查断言触发更改的情况,您可以递归执行方法 - 结果是多个断言或程序永远不会正常进入的状态。
据我了解断言功能,这是一个设计问题。该对话框与应用程序本身在同一个 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()
这清楚地表明,可以在断言打开时执行任意代码。
所以我正在寻找一种类似于断言的机制,它可以停止所有现有线程并在它自己的(线程)上下文中运行。有任何想法吗?