gpt4 book ai didi

c# - 关于异步任务,为什么需要 Wait() 来捕获 OperationCanceledException?

转载 作者:行者123 更新时间:2023-11-30 13:58:37 25 4
gpt4 key购买 nike

我正在遵循示例代码 here了解异步任务。我修改了代码以编写任务工作与主要工作的一些输出。输出将如下所示:

enter image description here

我注意到,如果我删除 Wait() 调用,程序运行相同,只是我无法捕获任务取消时抛出的异常。有人可以解释需要 Wait() 才能命中 catch block 的幕后发生了什么吗?

一个警告,Visual Studio 调试器将错误地停止在 Console.WriteLine("- task work"); 行并显示消息“OperationCanceledException 未被用户代码处理”。发生这种情况时,只需单击“继续”或按 F5 即可看到程序的其余部分运行。参见 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状态。

理想情况下,您想观察所有 Task异常(exception)。如果您使用 Task作为基于任务的异步模式的一部分,那么在某些时候你应该 await Task ,它在 Task 上传播第一个异常.如果您使用 Task s 作为任务并行库的一部分,那么在某些时候你应该调用 WaitTask<T>.Result ,它传播关于 Task 的所有异常, 包裹在 AggregateException 中.

如果你没有观察到 Task异常,那么当 Task完成后,运行时将引发 TaskScheduler.UnobservedTaskException然后忽略异常。 (这是 .NET 4.5 行为;4.5 之前的行为会引发 UnobservedTaskException,然后终止进程)。

在你的例子中,你没有等待任务完成,所以你退出了 try/catch block 。一段时间后,UnobservedTaskException被引发,然后异常被忽略。

关于c# - 关于异步任务,为什么需要 Wait() 来捕获 OperationCanceledException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16222132/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com