2016-11-17 116 views
-5

我编写了一个程序来检查我是否理解异步等待概念。异步并等待线程问题

 static void Main(string[] args) 
    { 
     Run2().Wait(); 
    } 

    static async Task DoAsyncWork() 
    { 
     await Task.Delay(2000); 
    } 

    static async Task Run2() 
    { 
     var tid = Thread.CurrentThread.ManagedThreadId; 
     await DoAsyncWork(); 
     Console.WriteLine(tid == Thread.CurrentThread.ManagedThreadId); 
    } 

我有点迷惑,会有什么打印?

我认为我们不能保证什么都会打印

我Explantion: 当await DoAsyncWork是调用控件回到主菜单。在DoAsyncWork之后 完成控制返回并在等待之后继续代码的其余部分。 其余的代码可以运行,我们没有关于巫婆线程运行此代码的保证。

其实: 我运行这段代码很多时间,并得到False打印。

+4

你打算问同样的问题多少次? http://stackoverflow.com/questions/40577858/async-await-thread-expected – Jim

+0

*我们没有关于巫婆线程运行此代码的保证。*如果'await'将安排继续而不是继续(因为它会做会看到已经完成的任务),那么我们保证继续将在'ThreadPool'线程之一运行。和以前一样,它不使用ThreadPool线程,它保证线程不同。 – PetSerAl

+1

你真的应该停止反复询问同一个问题。更好地阅读这篇文章,而不是:http://blog.stephencleary.com/2012/02/async-and-await.html – VMAtm

回答

4

await将使用SynchronizationContext.Current来确定如何执行延续代码。如果当前同步上下文中有一个值,并且同步上下文的特定实现最终会运行在特定线程上发送给它的所有代码,那么您将始终最终在同一线程中运行代码。 (WinForms或WPF应用程序设置的同步上下文会执行此操作)。

如果没有同步上下文(在您的代码中就是这种情况),将使用默认值,它使用线程池,因此它最终可能会在任何线程上运行。也可能有一个同步上下文集合,它不一定会在同一个线程上运行发送给它的所有代码。 (ASP应用程序使用的同步上下文会执行此操作。)

由于在您的代码中没有同步上下文,因此将使用线程池,并且线程永远不会相同。如果你创建了一个具有同步上下文的消息循环(比如说,当启动一个winforms或WPF应用程序时会发生这种情况)并且从中调用Run2,那么这些线程就会可靠地匹配。

+0

因此,如果上下文在await关键字之前和之后是相同的,那么这些线程将会是相同的? – maz

+0

@maz如果'await'之前没有默认的上下文,那么它就是在那个线程和上下文继续被调用的上下文之前,假设'await'有一些东西需要等待并且没有完成任务,在这种情况下执行将在当前线程中继续。 – PetSerAl

+0

@PetSerAl你可以给考试,假设上下文是asp上下文吗? – maz