为什么在等待方法之后,代码上没有使用初始线程?

Ber*_*ian 1 c# multithreading async-await

我不明白在使用async-await时控件是如何返回给调用者的,因为当我执行这段代码时,第一个线程在等待方法中调用task时几乎被破坏,并且给出结果的线程执行所有剩余的代码.我还画了一幅关于我如何看待执行的图表,但似乎是错的.

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

结果

结果

在此输入图像描述

主要

           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();

            }
Run Code Online (Sandbox Code Playgroud)

异步任务

         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;
           }
Run Code Online (Sandbox Code Playgroud)

任何人都可以指向正确的方向吗?还有什么原因导致新线程产生?总是在启动任务时?除了创建新线程以执行剩余代码的任务之外还有其他"触发器"吗?

Evk*_*Evk 5

async Main方法转换为如下所示:

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

static async Task RealMain() {
    // code from async Main
}
Run Code Online (Sandbox Code Playgroud)

考虑到这一点,在"从主要的异步调用之前"点,你在主应用程序线程(id 1).这是常规(非线程池)线程.你会在这个线程上直到

await Task.Factory.StartNew(...)
Run Code Online (Sandbox Code Playgroud)

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

当你到达时await- 控制权返回给调用者,在这种情况下,调用者是线程1.调查await后这个线程做了什么?它被阻止在这里:

 RealMain().GetAwaiter().GetResult();
Run Code Online (Sandbox Code Playgroud)

等待结果RealMain.

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

到达Console.ReadKey并按下一个键 - Main任务最终完成后,线程1(等待此任务完成)被解除阻塞,然后它从真正的Main函数返回并且进程终止(仅此时线程1被"销毁").

  • @Evk好的,所以有两个原因导致它无法将控制权返回给调用者.首先是`Thread1`正在等待'Thread3`完成,所以很忙.第二个是"Thread1"没有"同步上下文",因为这是一个控制台应用程序.在WPF/Winforms中有同步上下文,因此`Thread3`会想要返回控制,但是`Thread1`会忙于等待,所以我们会遇到死锁.那是对的吗? (2认同)