【问题标题】:Why am I seeing no difference between ConfigureAwait(false) and ConfigureAwait(true) here? [duplicate]为什么我在这里看不到 ConfigureAwait(false) 和 ConfigureAwait(true) 之间的区别? [复制]
【发布时间】:2023-03-22 10:40:01
【问题描述】:

我正在尝试为我在async-await 上所做的报告创建概念验证。

我做了一个示例代码

using System;
using System.Threading.Tasks;
using System.Threading;

public class Program
{
    static async Task CreateATaskThatPrintsWhichThread()
    {
        Console.WriteLine("Thread on line right before the bottom await = {0}", Thread.CurrentThread.ManagedThreadId);
        await Task.Run(() => 
        {
            Task.Delay(500);
            Console.WriteLine("Thread on line inside bottom task action = {0}", Thread.CurrentThread.ManagedThreadId);                         
        });
        Console.WriteLine("Thread on line right before the bottom await = {0}", Thread.CurrentThread.ManagedThreadId);
    }

    public static void Main()
    {
        Task.Run(async () =>
        {
            Console.WriteLine("Thread on line right before the bottom await = {0}", Thread.CurrentThread.ManagedThreadId);
            Task printStuff = CreateATaskThatPrintsWhichThread();
            printStuff.ConfigureAwait(true);
            await printStuff;
            Console.WriteLine("Thread on line right before the bottom await = {0}", Thread.CurrentThread.ManagedThreadId);
        }).Wait();
    }
}

我在 .NET Fiddle 上反复运行,结果是零星的:

Thread on line right before the bottom await = 14
Thread on line right before the bottom await = 14
Thread on line inside bottom task action = 28
Thread on line right before the bottom await = 28
Thread on line right before the bottom await = 28


Thread on line right before the bottom await = 28
Thread on line right before the bottom await = 28
Thread on line inside bottom task action = 28
Thread on line right before the bottom await = 28
Thread on line right before the bottom await = 28


Thread on line right before the bottom await = 28
Thread on line right before the bottom await = 28
Thread on line inside bottom task action = 53
Thread on line right before the bottom await = 53
Thread on line right before the bottom await = 28

等等。当我更改为 `printStuff.ConfigureAwait(false);

Thread on line right before the bottom await = 99
Thread on line right before the bottom await = 99
Thread on line inside bottom task action = 87
Thread on line right before the bottom await = 36
Thread on line right before the bottom await = 99

Thread on line right before the bottom await = 45
Thread on line right before the bottom await = 45
Thread on line inside bottom task action = 36
Thread on line right before the bottom await = 36
Thread on line right before the bottom await = 45

Thread on line right before the bottom await = 25
Thread on line right before the bottom await = 25
Thread on line inside bottom task action = 12
Thread on line right before the bottom await = 12
Thread on line right before the bottom await = 25

有人可以告诉我结果“应该”是什么,或者可以帮助我在 .NET Fiddle 上创建一个更好的示例吗?

(我也很困惑,因为我认为Task.Run里面的行基本上保证在后台线程上执行)

【问题讨论】:

  • 您是否发现一半的日志记录使用的字符串与您的日志记录中已经使用的其他字符串无法区分?因为我觉得这很令人困惑。
  • 为什么要丢弃 ConfigureAwait 返回的任务?
  • 你应该从编译器那里得到一个解释问题的警告;您是否忽略了警告?当您的某些代码似乎无法正常工作时,请考虑阅读编译器警告;这些警告试图告诉你为什么代码不能正常工作。
  • 回复:“我也很困惑,因为我认为 Task.Run 内部的行基本上可以保证在后台线程上执行”——你没有证明线程用于执行不是后台线程。更改日志以在线程上打印出IsBackground 的结果,您会发现它始终是后台线程。
  • 但是你的基本问题是关于为什么你没有看到基于你是否需要在当前上下文上执行延续的行为差异。与其试图描述一个差异,不如说明你期望看到什么行为,然后你期望看到什么时候它是错误的。是否违反了您的任何一个期望?如果不是,那有什么问题?如果是,那么你有一个不正确的期望,所以让我们陈述它是什么并消除你的错误信念。

标签: c# .net asynchronous async-await


【解决方案1】:

cmets 涵盖了大部分内容,但由于还没有答案,我认为您所追求的答案是您错误地得出结论,.ConfigureAwait(true) 意味着在await 之后,代码将继续在和以前一样。

这是真的在某些情况下,尤其是那些具有某种形式的消息/调度程序循环的情况。在这些情况下,当 pre-continuation 代码完成时,捕获的 SynchronizationContext 用于将请求发送回调度程序 - 当它下一个能够时 - 获取延续并继续在其线程上执行它。循环通常连续快速地旋转,服务于 UI 问题,一旦注册帖子,它将使用其迭代之一来执行延续。

控制台应用程序没有这样的循环,也没有SynchronizationContext,因此执行延续的任务改为排队到线程池中,任何可用的线程都会执行它。您偶尔会很幸运,并以与继续之前相同的线程结束,但这只是偶然。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多