为什么在等待的方法之后在代码上不使用初始线程? [英] Why is the initial thread not used on the code after the awaited method?

查看:34
本文介绍了为什么在等待的方法之后在代码上不使用初始线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不明白使用async-wait时控件如何返回给调用者,因为当我执行此代码时,在等待的方法内调用task时,第一个线程实际上被破坏了,给出结果的线程执行了所有剩余的代码.下面我还绘制了一个我认为执行是如何的图,但似乎是错误的.

I do not understand how is the control returned to the caller when using async- await, since when i execute this code, the first thread gets practically destroyed when calling task inside the awaited method, and the thread that gives the result executes all remaining code.Below i have also drawn a diagram of how i thought the execution is, but it seems it is wrong.

根据将控制权返回给呼叫者"的假定工作流程:

结果

主要

           public static string GetThreadId => Thread.CurrentThread.ManagedThreadId.ToString();

           static async Task Main(string[] args) {
                Console.WriteLine("From main before async call , Thread:" + GetThreadId);

                string myresult = await TestAsyncSimple();

                Console.WriteLine("From main after async call ,Thread:" + GetThreadId);
                Console.WriteLine("ResultComputed:" + myresult+",Thread:"+GetThreadId);
                Console.ReadKey();

            }

异步任务

         public static async Task<string> TestAsyncSimple() {

            Console.WriteLine("From TestAsyncSimple before delay,Thread:" + GetThreadId);
            string result=await Task.Factory.StartNew(() => {
                Task.Delay(5000);
                Console.WriteLine("From TestAsyncSimple inside Task,Thread:" + GetThreadId);
                return "tadaa";
                });
            Console.WriteLine("From TestAsyncSimple after delay,Thread:" + GetThreadId);
            return result;
           }

有人能指出我正确的方向吗?又是什么导致新线程产生?总是在启动Task时?除了创建新线程并执行其余代码的任务之外,还有其他触发因素"吗?

Can anyone point me to the right direction?Also what causes the new thread to get spawned?Always when starting a Task ?Are there other "triggers" besides tasks that create new threads which will execute the remaining code?

推荐答案

异步主方法被转换为如下形式:

async Main method is converted to something like this:

static void Main() {
    RealMain().GetAwaiter().GetResult();
}

static async Task RealMain() {
    // code from async Main
}

请记住,在从异步调用前从主"开始时,您位于主应用程序线程(标识1)上.这是常规(非线程池)线程.您将一直处于该线程上,直到

With that in mind, at "From main before async call" point you are on main application thread (id 1). This is regular (non thread pool) thread. You will be on this thread until

await Task.Factory.StartNew(...)

此时, StartNew 启动一个新任务,该任务将在线程池线程上运行,该线程将在线程池中创建或从线程池中获取(如果已经可用).这是您示例中的线程3.

At this point, StartNew starts a new task which will run on a thread pool thread, which is created or grabbed from pool if already available. This is thread 3 in your example.

当您到达 await 时-控制权返回给调用者,在这种情况下,调用者是线程1.在这里被屏蔽了:

When you reach await - control is returned back to the caller, where caller in this case is thread 1. What this thread does after await is reched? It's blocked here:

 RealMain().GetAwaiter().GetResult();

等待 RealMain 的结果.

现在线程3已完成执行,但是 TestAsyncSimple()有更多代码要运行.如果等待之前没有同步上下文(在此情况-在控制台应用程序中),则等待之后的部分将在可用线程池线程上执行.由于线程3已完成其任务的执行-它是可用的,并且能够继续执行它的其余 TestAsyncSimple() Main()函数.如上所述,线程1一直处于阻塞状态-因此它无法处理任何继续(忙).此外,它也不是线程池线程(但是这里不是相关事件).

Now thread 3 has finished execution but TestAsyncSimple() has more code to run. If there were no synchronization context before await (the case here - in console application) - the part after await will be executed on available thread pool thread. Since thread 3 has finished execution of its task - it is available and is capable to continue execution of the rest of TestAsyncSimple() and Main() functions, which it does. Thread 1 all this time is blocked as said above - so it cannot process any continuations (it's busy). In addition it's also not a thread pool thread (but that is not relevent here).

到达 Console.ReadKey 并按下键后- Main 任务最终完成,线程1(等待此任务完成)被解除阻塞,然后从真正的Main函数和过程终止(仅在这一点上线程1被销毁").

After you reached Console.ReadKey and pressed a key - Main task finally completes, thread 1 (waiting for this task to complete) is unblocked, then it returns from real Main function and process is terminated (only at this point thread 1 is "destroyed").

这篇关于为什么在等待的方法之后在代码上不使用初始线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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