gpt4 book ai didi

c# - CancellationToken 阻塞线程执行

转载 作者:行者123 更新时间:2023-12-03 12:48:05 25 4
gpt4 key购买 nike

我正在尝试使用取消标记从另一个线程中跳出循环:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace CancellationTokenTest
{
class Program
{
private static CancellationTokenSource token;

static async Task Main(string[] args)
{
token = new CancellationTokenSource();
var t1 = LongProcess1();

for (int i = 0; i < 5; i++)
{
try
{
await Task.Delay(2000, token.Token);
Console.WriteLine($"Main awaited {i}");
}
catch (OperationCanceledException)
{
break;
}
}

Console.WriteLine("Main loop completed");
t1.Wait();
Console.WriteLine("Application end");
}

static async Task LongProcess1()
{
for (int i = 0; i < 5; i++)
{
await Task.Delay(1000);
Console.WriteLine($"LongProcess1 awaited {i}");
}

Console.WriteLine("Submitting cancel");
token.Cancel(); // <------ Blocking execution
Console.WriteLine("Cancellation done!");
}
}
}

问题是行 Console.WriteLine("Cancellation done!"); 永远不会被执行,并且 Main() 方法一直在等待 t1 完成。

我不明白为什么!

我在 .NET 5 上运行它,但它似乎不依赖于框架。有人可以帮助我了解发生了什么吗?

最佳答案

这个死锁与described on my blog 几乎完全一样.您需要注意的一件事是,在这种情况下,CancellationTokenSource.Cancel 正在调用 Cancel 的线程上运行取消 token 延续。

所以,这是正在发生的事情:

  • Main 启动 LongProcess
  • LongProcess 使用一些 await 并在线程池线程上恢复。
  • 与此同时,Main 正在执行 await Task.Delay
  • LongProcess 执行Cancel 时,它实际上恢复执行当前线程 上的Main 方法。您可以通过在 catch block 中放置一个断点并查看调用堆栈来验证这一点。
  • 然后当前线程(线程池线程)阻塞任务 (.Wait())。
  • 现在,LongProcess 无法完成,因为当前运行它的线程被阻塞等待它完成。

要修复它,请将 Wait() 更改为 await

关于c# - CancellationToken 阻塞线程执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65994328/

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