0

我的理解是,在 Windows 窗体应用程序中,如果 UI 线程抛出异常并且不由用户代码处理,则应用程序将以用户显而易见的方式崩溃。(屏幕上将出现一条消息,指示应用程序已崩溃,或窗口将冻结,或两者兼而有之)

现在考虑以下代码:

try
{
     PerformAsyncOperation();
     while(!async_op_complete)
     {
           Application.DoEvents();
     }
}
catch
{
    Print("exception");
}

我不明白的是,因为 Windows 窗体具有同步上下文,所以在控制离开事件处理程序之前不会执行异步操作(顺便说一下,我不是在谈论 .net 4.5)。一旦发生这种情况,异步代码将在 UI 线程内运行。如果该代码要引发异常,则它不会被围绕异步方法调用的 try-catch 语句捕获,因为在引发异常时控制已经离开了该 try-catch 语句。

但在上述情况下,我们正在循环的事实意味着控制保留在 UI 线程中,而我们在循环中调用 Application.DoEvents() 的事实意味着异步操作在内部“异步”执行用户界面线程。并且由于该循环发生在 try 子句中,因此 async 方法抛出的任何异常都将被相应的 catch 子句捕获。(至少这是我观察到的行为。)

也就是说,

  1. 在循环中调用 Application.DoEvents() 以保持 UI 响应,同时等待异步操作完成,然后继续在同一个 UI 线程中做更多工作,这是一个好主意吗?

  2. Even if it's not a good idea to call Application.DoEvents() inside a loop, why does the application quietly exit (no window freezes, no error messages) after the catch clause handles the exception thrown by PerformAsyncOperation()?

4

1 回答 1

1

1) Is it ever a good idea to call Application.DoEvents() inside a loop in order to keep the UI responsive while waiting for an async operation to complete before moving on to doing more work inside the same UI thread?

Absolutely Not! DoEvents() is evil and will cause you all sorts of problems.

2) Even if it's not a good idea to call Application.DoEvents() inside a loop, why does the application quietly exit (no window freezes, no error messages) after the catch clause handles the exception thrown by PerformAsyncOperation()?

Difficult to say without knowing what PerformAsyncOperation() does. Unless it explicitly uses a new Thread ( or Task ), it will execute synchronously before your loop.

As for the app exit - I can't explain that.

If an uncaught exception is thrown on a worker Thread, the app will show the "stopped working" dialog box and exit.

The only thing I know that has changed is the behaviour when an uncaught exception is thrown from inside a Task. Prior to .NET 4.5, this would cause a fast fail as with a Thread.

If you have installed .NET 4.5 ( even if the app targets 4.0 ) an uncaught exception in a Task is now silently swallowed.

Here's an article that explains the behaviours: MSDN: Task Exception Handling in .NET 4.5

于 2013-03-21T15:49:27.540 回答