为了使开发人员更容易编写基于Tasks的异步代码,.NET 4.5更改了未观察到的异常的默认异常行为.虽然未观察到的异常仍会导致引发UnobservedTaskException事件(不会这样做会发生重大变化),默认情况下进程不会崩溃.相反,无论事件处理程序是否观察到异常,异常将在引发事件后最终被吃掉.
但是我的实验结果与上述说法不符.以下是我的代码:
static void Main(string[] args)
{
DownloadAsync("http://an.invalid.url.com);
}
async static void DownloadAsync(string url)
{
using (var client = new System.Net.Http.HttpClient())
{
string text = await client.GetStringAsync(url);
Console.WriteLine("Downloaded {0} chars", text.Length);
}
}
Run Code Online (Sandbox Code Playgroud)
因为我传递一个无效的URL DownloadAsync()方法,调用HttpClient的GetStringAsync()方法会抛出一个expcetion,并且它的应用程序崩溃.
所以我的问题是:默认情况下,.NET 4.5中未观察到的异常是否仍然会崩溃应用程序?
Ste*_*ary 31
你有一个Task异常(返回的那个GetStringAsync).然而,await正在观察Task异常,然后该异常传播出该DownloadAsync方法(即async void).
传播出async void方法的异常行为不同; 它们是SynchronizationContext在async void方法启动时激活的(在本例中为线程池SynchronizationContext).这不被视为未被观察到的例外.
如果您更改DownloadAsync为return Task,那么您将有一个实际的未观察到的Task异常,将被忽略(正确):
static void Main(string[] args)
{
DownloadAsync("http://an.invalid.url.com);
Console.ReadKey();
}
async static Task DownloadAsync(string url)
{
using (var client = new System.Net.Http.HttpClient())
{
string text = await client.GetStringAsync(url);
Console.WriteLine("Downloaded {0} chars", text.Length);
}
}
Run Code Online (Sandbox Code Playgroud)