ConfigureAwait将继续项推送到池线程中

问题描述 投票:9回答:3

这里是一些WinForms代码:

async void Form1_Load(object sender, EventArgs e)
{
    // on the UI thread
    Debug.WriteLine(new { where = "before", 
        Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread });

    var tcs = new TaskCompletionSource<bool>();

    this.BeginInvoke(new MethodInvoker(() => tcs.SetResult(true)));

    await tcs.Task.ContinueWith(t => { 
        // still on the UI thread
        Debug.WriteLine(new { where = "ContinueWith", 
            Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread });
    }, TaskContinuationOptions.ExecuteSynchronously).ConfigureAwait(false);

    // on a pool thread
    Debug.WriteLine(new { where = "after", 
        Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread });
}

输出:

{其中=之前,ManagedThreadId = 10,IsThreadPoolThread = False}{其中= ContinueWith,ManagedThreadId = 10,IsThreadPoolThread = False}{其中=之后,ManagedThreadId = 11,IsThreadPoolThread = True}

为什么ConfigureAwait在这里主动将await延续推送到池线程?

我使用“推送到池线程”]在此描述当在一个线程上调用主连续回调(actionTaskAwaiter.UnsafeOnCompleted参数,但在第二个回调( [TaskAwaiter.UnsafeOnCompleted)排队到池线程。

ConfiguredTaskAwaiter.UnsafeOnCompleted说:

continueOnCapturedContext ...尝试将其编组为true继续回到捕获的原始上下文;否则为假。

我知道当前线程上安装了ConfiguredTaskAwaiter.UnsafeOnCompleted。尽管如此,仍要进行没有尝试封送],执行点已经存在。

因此,它更像是“永远不要继续捕获原始上下文”

...

按预期,如果执行点已经在没有同步上下文的池线程上,则没有线程切换:

docs
{其中=之前,ManagedThreadId = 10,IsThreadPoolThread = False}{其中= ContinueWith,ManagedThreadId = 6,IsThreadPoolThread = True}{其中=之后,ManagedThreadId = 6,IsThreadPoolThread = True}

Updated

,再进行一次测试以查看any是否同步。上下文不足以进行延续(而不是原始的上下文)。确实是这样:
WinFormsSynchronizationContext
{其中=之前,ManagedThreadId = 9,IsThreadPoolThread = False}{其中=新线程,ManagedThreadId = 10,IsThreadPoolThread = False}{其中= ContinueWith,ManagedThreadId = 10,IsThreadPoolThread = False}{其中=之后,ManagedThreadId = 6,IsThreadPoolThread = True}

[这里是一些WinForms代码:async void Form1_Load(object sender,EventArgs e){//在UI线程上Debug.WriteLine(new {其中=“ before”,Thread.CurrentThread.ManagedThreadId,...

c# .net multithreading task-parallel-library async-await
3个回答
15
投票

为什么ConfigureAwait在这里主动将等待继续推送到池线程?


12
投票

这里是根据await FooAsync(true).ConfigureAwait(false); 的挖掘对这种行为的解释。


8
投票

我认为以稍微不同的方式想到这一点最容易。

© www.soinside.com 2019 - 2024. All rights reserved.