Axi*_*xus 8 c# multithreading asynchronous async-await
让我发一个简单的例子:
    private void MyMethod()
    {
        Task task = MyAsyncMethod();
        task.Wait();
    }
    private async Task MyAsyncMethod()
    {
        //Code before await
        await MyOtherAsyncMethod();
        //Code after await
    }
假设我在一个单线程应用程序中运行上面的代码 - 就像一个控制台应用程序 - .我很难理解代码//Code after await是如何运行的.
我明白当我await在MyAsyncMethod()控制中点击关键字时会回到原点MyMethod(),但后来我将锁定该线程task.Wait().如果线程被锁定,//Code after await如果应该接受它的线程被锁定,怎么能运行?
是否创建了一个新线程来运行//Code after await?或者主线程神奇地走出task.Wait()去运行//Code after await?
我不确定这是怎么回事?
Sri*_*vel 15
如果从主线程调用,则在Winform App中发布的代码将是"死锁",因为你正在用Wait().阻止主线程.
但在控制台应用程序中这是有效 但怎么样?
答案隐藏在SynchronizationContext.Current.await捕获"SynchronizationContext",当任务完成时,它将继续在相同的"SynchronizationContext"中.
在winform应用程序SynchronizationContext.Current将设置为WindowsFormsSynchronizationContext将发布到"消息循环"的调用,但谁将处理该?主线程正在等待Wait().
在控制台应用程序中SynchronizationContext.Current默认不会设置,所以null当没有"SynchronizationContext"可用于等待捕获时,它将调度继续ThreadPool(TaskScheduler.Default,这是ThreadpoolTaskScheduler),因此等待后的代码工作(通过线程池线程) .
前面提到的捕获行为可以通过使用来控制,Task.ConfigureAwait(false);这将阻止winform应用程序死锁,但代码await不再在UI线程中运行.
Jon*_*eet 12
是否创建了一个新线程来等待?
也许.也许不吧.等待模式实现使用在await表达式开始时为"当前"的同步上下文来Task运行continuation(await表达式之后的位).例如,如果您处于UI线程的上下文中,则意味着您将最终返回到相同的UI线程.如果你在一个线程池线程中,你将最终回到某个线程池线程,但它可能是一个不同的线程.
当然,使用您的代码示例,如果您在UI线程中,您的调用Wait()将阻止UI线程,以便继续无法运行 - 您需要注意这一点.(调用Wait()或Result执行您不知道要完成的任务,以及可能需要在当前线程上工作的任务,这是一个坏主意.)
请注意,您可以调用Task.ConfigureAwait,这样就可以表达的意图不要求继续在同样的背景下.这通常适用于不关心它们运行在哪个线程上的库方法:
await task.ConfigureAwait(false);
(它影响的不仅仅是线程 - 它是捕获与否的整个上下文.)
我认为通过等待来熟悉引擎盖下的内容是个好主意.网上有很多文档,如果你允许我一个简短的插件,还有第三版的C#深度,以及关于这个主题的Tekpub截屏系列.或者从MSDN开始,然后从那里开始.
| 归档时间: | 
 | 
| 查看次数: | 3203 次 | 
| 最近记录: |