gpt4 book ai didi

c# - 在方法签名中使用异步时,任务取消异常不会冒泡

转载 作者:太空宇宙 更新时间:2023-11-03 11:11:51 25 4
gpt4 key购买 nike

这个我不是很懂。在我下面的代码中,按原样运行,token.ThrowIfCancellationRequested() 抛出的异常不会被发送回 Main 使用 .Wait() 的位置,而是当场抛出,堆栈跟踪并不知道它发生在哪里除了“任务被取消”之外。但是,如果我删除 async 关键字并使用 await Task.Delay() 删除 try catch block ,它确实会发送回 main 中的 .Wait() 并在那里被捕获。

我是不是做错了什么,或者我究竟是如何让 await Task.Delay() 和 token.ThrowIfCancellationRequested() 抛出的异常同时冒泡到 .Wait()?

static void Main(string[] args)
{
var t = new CancellationTokenSource();
var task = Task.Factory.StartNew((x) => Monitor(t.Token), t.Token, TaskCreationOptions.LongRunning);

while (true)
{
if (Console.ReadLine() == "cancel")
{
t.Cancel();
try
{
task.Wait();
}
catch(AggregateException)
{
Console.WriteLine("Exception via task.Wait()");

}
Console.WriteLine("Cancelled");
}
}
}

static async void Monitor(CancellationToken token)
{
while(true)
{
for(int i = 0; i < 5; i++)
{
// If the async in the method signature, this does not send the exception to .Wait();
token.ThrowIfCancellationRequested();

// Do Work
Thread.Sleep(2000);
}

// Wait 10 seconds before doing work again.

// When this try block is removed, and the async is taken out of the method signature,
// token.ThrowIfCancellationRequested() properly sends the exception to .Wait()
try
{
await Task.Delay(10000, token);
}
catch(TaskCanceledException)
{
Console.WriteLine("Exception from Delay()");
return;
}
}
}

最佳答案

你应该避免async void。它的异常处理语义很棘手,并且不可能组合到其他 async 方法中。

async void 方法在概念上是事件处理程序,因此如果它抛出异常,将直接在其 SynchronizationContext 上引发 - 在这种情况下,会在线程池上引发线程。

void-返回方法的异步等价物不是async void-返回方法;它是一个 async Task 返回方法。所以你的 Monitor 方法应该返回 Task:

static void Main(string[] args)
{
var t = new CancellationTokenSource();
var task = Monitor(t.Token);

while (true)
{
if (Console.ReadLine() == "cancel")
{
t.Cancel();
try
{
task.Wait();
}
catch(AggregateException)
{
Console.WriteLine("Exception via task.Wait()");
}
Console.WriteLine("Cancelled");
}
}
}

static async Task Monitor(CancellationToken token)

不用担心缺少 LongRunning 标志;这只是一种优化,没有它线程池也能正常工作。

你可以找到我的 async/await introofficial MSDN documentation有帮助。

关于c# - 在方法签名中使用异步时,任务取消异常不会冒泡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13696791/

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