我不明白在使用async-await时控件是如何返回给调用者的,因为当我执行这段代码时,第一个线程在等待方法中调用task时几乎被破坏,并且执行结果的线程执行剩下的所有代码。我还画了一个关于我如何看待执行的图表,但似乎是错误的。
根据&#34假设工作流程;将控制权交还给来电者":
结果
主要
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;
}
任何人都可以指出我正确的方向吗?还有什么原因导致新线程产生?总是在启动任务时?还有其他&#34;触发器&#34;除了创建将执行剩余代码的新线程的任务?
答案 0 :(得分:5)
async主方法转换为类似的东西:
static void Main() {
RealMain().GetAwaiter().GetResult();
}
static async Task RealMain() {
// code from async Main
}
考虑到这一点,在&#34;来自主要的异步呼叫之前&#34;指出你是主应用程序线程(id 1)。这是常规(非线程池)线程。你将在这个主题上直到
await Task.Factory.StartNew(...)
此时,StartNew
启动一个新任务,该任务将在线程池线程上运行,如果已经可用,该线程将从池中创建或获取。这是你的例子中的第3个帖子。
当你到达await
时 - 控制权返回给调用者,在这种情况下,调用者是线程1.在调用await之后这个线程做了什么?它被阻止了:
RealMain().GetAwaiter().GetResult();
等待RealMain
的结果。
现在线程3已经完成执行,但TestAsyncSimple()
有更多代码要运行。如果在await之前没有同步上下文(这里的情况 - 在控制台应用程序中) - await之后的部分将在可用的线程池线程上执行。由于线程3已完成其任务的执行 - 它可用并且能够继续执行其余的TestAsyncSimple()
和Main()
函数。如上所述,线程1一直被阻止 - 因此它不能处理任何延续(它很忙)。此外,它也不是线程池线程(但这里不相关)。
到达Console.ReadKey
并按下一个键 - Main
任务最终完成后,线程1(等待此任务完成)被解除阻塞,然后从真正的Main函数返回并终止进程(只有在这一点上,线程1才会被销毁&#34;)。