gpt4 book ai didi

c# - 异步线程体循环,它只是工作,但如何?

转载 作者:太空狗 更新时间:2023-10-29 20:20:15 25 4
gpt4 key购买 nike

我刚刚测试了一些我确信会失败的东西,但令我惊讶的是,它完美地工作,并向我自己证明我仍然对 async-await 的工作原理感到困惑。

我创建了一个线程,传递一个 async void 委托(delegate)作为线程的主体。这是我的代码的过度简化:

var thread = new Thread( async () => {
while( true ) {
await SomeLengthyTask();
...
}
});
thread.Start();
thread.Join();

据我所知,当执行遇到 await 关键字时,方法会隐式返回,在本例中是循环线程的主体,而其余部分代码的一部分包含在回调延续中。

由于这个事实,我非常确定线程会在 await 产生执行后立即终止,但事实并非如此!

有人知道这个魔法是如何实际实现的吗? async 功能是否被剥离并且 async 同步等待,或者是否有一些黑色CLR 施展魔法,使其能够恢复因 await 而产生的线程?

最佳答案

线程确实很快就终止了。

但由于 Thread 构造函数不接受 async lambda,因此您得到的是一个 async void 委托(delegate)。

原始线程将结束,continuation(await 之后的其余部分)将被发布到 ThreadPool 并最终在另一个线程上运行。

您可以通过检查线程 ID 来测试它:

var thread = new Thread(async () =>
{
while (true)
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
await SomeLengthyTask();
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
}
});
thread.Start();
thread.Join();

Console.ReadLine();

输出:

3
5
5
...
5

为了使示例更简单,我们假设您有此 Run 方法:

void Run(Action action)
{
action();
}

然后你用你的async委托(delegate)调用它

Run(async () => 
{
while(true)
{
await SomeLengthyTask();
...
}
});

Run 的执行将在到达第一个 await 并返回时几乎立即完成。 async 委托(delegate)的其余部分将通过另一个线程在 ThreadPool 上继续。


通常,每次您在执行 async 方法时到达 await 时,线程就会丢失,继续(等待任务完成后的其余部分)将被发布到 ThreadPool(除非存在 SynchronizationContext,就像在 UI 线程中一样)。它可能会在同一个线程上执行(如我的示例中的 5),但也可能不会。

在您的情况下,您显式创建的线程不是 ThreadPool 的一部分,因此它肯定会终止,其余线程将在不同的线程上运行。

关于c# - 异步线程体循环,它只是工作,但如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30044846/

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