异步线程主体循环,它只是有效,但是如何? [英] Async thread body loop, It just works, but how?

查看:53
本文介绍了异步线程主体循环,它只是有效,但是如何?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚测试了一些我肯定会失败的东西,但令我惊讶的是,它完美无缺地工作,并向我证明了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆