异步线程主体循环,它只是有效,但是如何? [英] Async thread body loop, It just works, but how?
问题描述
我刚刚测试了一些我肯定会失败的东西,但令我惊讶的是,它完美无缺地工作,并向我证明了async-await
的工作原理我仍然很迷惑.
I have just tested something that I was sure would fail miserably, but to my surprise, it worked flawlessly, and proves to myself that I am still quite mystified by how async-await
works.
我创建了一个线程,并传递了async void
委托作为线程的主体.
这是我的代码的过度简化:
I created a thread, passing an async void
delegate as the thread's body.
Here's an oversimplification of my code:
var thread = new Thread( async () => {
while( true ) {
await SomeLengthyTask();
...
}
});
thread.Start();
thread.Join();
据我所知,当执行命中await
关键字时,方法会隐式返回,在这种情况下,循环线程的主体会被隐藏,而其余代码将被包装在回调的延续中.
The thing is that as far as I understand, when the execution hits the await
keyword, there is an implicit return from the method, in this case the body of the looping thread, while the rest of the code is wrapped in a callback continuation.
由于这个事实,我非常确定线程将在await
产生执行后立即终止,但事实并非如此!
Because of this fact, I was pretty sure that the thread would terminate as soon as the await
yielded execution, but that's not the case!
有人知道该魔术实际上是如何实现的吗? async
功能是否已被剥离并且async
同步等待,或者CLR是否正在执行某些黑魔术使它能够是否恢复由于await
而产生的线程?
Does anybody know how this magic is actually implemented? Is the async
functionality stripped down and the async
waits synchronously or is there some black magic being done by the CLR that enables it to resume a thread that has yielded because of an await
?
推荐答案
线程确实很快终止了.
但是由于Thread
构造函数不接受async
lambda,所以您得到的是一个async void
委托.
But since the Thread
constructor doesn't accept an async
lambda what you got there is an async void
delegate.
原始线程将结束,并且延续(await
之后的其余部分)将发布到ThreadPool
,并最终在另一个线程上运行.
The original thread will end and the continuation (the rest after the await
) will be posted to the ThreadPool
and eventually run on another thread.
您可以通过检查线程ID来进行测试:
You can test that by checking the thread 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
方法:
To make the example simpler let's assume you have this Run
method:
void Run(Action action)
{
action();
}
然后与您的async
代表
Run(async () =>
{
while(true)
{
await SomeLengthyTask();
...
}
});
Run
的执行几乎会在到达第一个await
并返回时立即完成. async
委托的其余部分将继续在ThreadPool
上使用另一个线程.
The execution of Run
will complete almost immediately when it reaches the first await
and returns. The rest of the async
delegate will continue on the ThreadPool
with another thread.
通常,每次执行async
方法时到达await
时,线程都会丢失,并且继续(等待任务完成后的其余部分)将被发布到ThreadPool中(除非存在SynchronizationContext)当前,例如在UI线程中).可能是它的执行将在同一线程上(如我的示例中的5),但也可能不在同一线程上.
Generally, each time you reach an await
in the execution of an async
method the thread is lost and the continuation (the rest after the awaited task completes) will be posted to the ThreadPool (unless if there's a SynchronizationContext present, like in the UI thread). It may be that it execution will be on the same thread (as in my example with 5) but it also may not.
在您的情况下,您显式创建的线程不属于ThreadPool
的一部分,因此它肯定会终止,其余线程将在另一个线程上运行.
In your case the thread you create explicitly isn't part of the ThreadPool
so it will definitely be terminated and the rest will run on a different thread.
这篇关于异步线程主体循环,它只是有效,但是如何?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!