我正在遵循示例代码here http://msdn.microsoft.com/en-us/library/dd997396.aspx了解异步任务。我修改了代码以编写任务工作与主要工作的一些输出。输出将如下所示:
我注意到,如果删除 Wait() 调用,程序会以相同的方式运行,只是我无法捕获取消任务时引发的异常。有人可以解释一下幕后发生了什么需要 Wait() 才能命中 catch 块吗?
一个警告,Visual Studio 调试器将错误地停止在Console.WriteLine(" - task work");
带有消息“OperationCanceledException 未由用户代码处理”的行。发生这种情况时,只需单击“继续”或按 F5 即可查看程序的其余部分运行。看http://blogs.msdn.com/b/pfxteam/archive/2010/01/11/9946736.aspx http://blogs.msdn.com/b/pfxteam/archive/2010/01/11/9946736.aspx了解详情。
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
class Program
{
static void Main()
{
var tokenSource = new CancellationTokenSource();
var cancellationToken = tokenSource.Token;
// Delegate representing work that the task will do.
var workDelegate
= (Action)
(
() =>
{
while (true)
{
cancellationToken.ThrowIfCancellationRequested();
// "If task has been cancelled, throw exception to return"
// Simulate task work
Console.WriteLine(" - task work"); //Visual Studio
//erroneously stops on exception here. Just continue (F5).
//See http://blogs.msdn.com/b/pfxteam/archive/2010/01/11/9946736.aspx
Thread.Sleep(100);
}
}
);
try
{
// Start the task
var task = Task.Factory.StartNew(workDelegate, cancellationToken);
// Simulate main work
for (var i = 0; i < 5; i++)
{
Console.WriteLine("main work");
Thread.Sleep(200);
}
// Cancel the task
tokenSource.Cancel();
// Why is this Wait() necessary to catch the exception?
// If I reomve it, the catch (below) is never hit,
//but the program runs as before.
task.Wait();
}
catch (AggregateException e)
{
Console.WriteLine(e.Message);
foreach (var innerException in e.InnerExceptions)
Console.WriteLine(innerException.Message);
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
当异常被抛出时ThrowIfCancellationRequested
,它传播出你的Task
代表。此时,它被框架捕获并添加到该异常的列表中Task
。同时,那Task
被过渡到Faulted
state.
理想情况下,您想要观察您的所有Task
例外情况。如果您正在使用Task
作为基于任务的异步模式的一部分,那么在某些时候您应该await
the Task
,这会传播第一个异常Task
。如果您正在使用Task
s 作为任务并行库的一部分,那么在某个时候你应该调用Wait
or Task<T>.Result
,它传播所有异常Task
,包裹在AggregateException
.
如果您没有观察到Task
例外,那么当Task
完成后,运行时间将提高TaskScheduler.UnobservedTaskException
然后忽略异常。 (这是 .NET 4.5 的行为;4.5 之前的行为会引发UnobservedTaskException
然后终止该进程)。
在您的情况下,您不会等待任务完成,因此您退出了 try/catch 块。一段时间之后,UnobservedTaskException
引发,然后忽略异常。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)