【问题标题】:Task.Run with or without async and awaitTask.Run 有或没有 async 和 await
【发布时间】:2020-05-25 02:45:56
【问题描述】:

任何人都可以解释使用 Task.Run 有或没有 async 和 await 的区别,如下面的代码,例如await Task.Run(async ()=>...)?

 public class AsyncRun
    {

        public void Entry()
        {
            Test4().Wait();
        }

        private async Task Test4()
        {
            Console.WriteLine($"1 {DateTime.Now}");

            await Task.Run(async () => await Get());

            Console.WriteLine($"2 {DateTime.Now}");

            Console.Read();

            //1 23 / 05 / 2020 07:52:42
            //Get 1 23 / 05 / 2020 07:52:42
            //Get 2 23 / 05 / 2020 07:52:43
            //2 23 / 05 / 2020 07:52:43

        }


        private Task Test3()
        {
            Console.WriteLine($"1 {DateTime.Now}"); 

            Task.Run(async ()=> await Get());

            Console.WriteLine($"2 {DateTime.Now}");

            Console.Read();

            return Task.CompletedTask;

            //1 23 / 05 / 2020 07:47:24
            //2 23 / 05 / 2020 07:47:24
            //Get 1 23 / 05 / 2020 07:47:24
            //Get 2 23 / 05 / 2020 07:47:25
        }

        private async Task Test2()
        {
            Console.WriteLine($"1 {DateTime.Now}");
            await Task.Run(Get);

            Console.WriteLine($"2 {DateTime.Now}");

            Console.Read();

            //1 23 / 05 / 2020 07:43:24
            //Get 1 23 / 05 / 2020 07:43:24
            //Get 2 23 / 05 / 2020 07:43:25
            //2 23 / 05 / 2020 07:43:25
        }

        private void Test1()
        {
            Console.WriteLine($"1 {DateTime.Now}");
            Task.Run(Get);

            Console.WriteLine($"2 {DateTime.Now}");

            Console.Read();

            //1 23 / 05 / 2020 07:41:09
            //2 23 / 05 / 2020 07:41:09
            //Get 1 23 / 05 / 2020 07:41:09
            //Get 2 23 / 05 / 2020 07:41:10
        }

        private Task Get()
        {
            Console.WriteLine($"Get 1 {DateTime.Now}");
            Thread.Sleep(1000);
            Console.WriteLine($"Get 2 {DateTime.Now}");
            return Task.CompletedTask;
        }
    }

【问题讨论】:

标签: c# asp.net-core .net-core


【解决方案1】:

差异显示在您的 Console.WriteLines 输出中。

当您使用await Task.Run 时,您正在等待您运行的任务完成,然后继续执行代码,因此您将获得以下日志:

// 1 23 / 05 / 2020 07:52:42
// Get 1 23 / 05 / 2020 07:52:42
// Get 2 23 / 05 / 2020 07:52:43
// 2 23 / 05 / 2020 07:52:43

当您不等待刚刚运行的任务时,就好像您正在运行它并“忘记”它。这意味着您的代码将继续执行,而您运行的任务将在其他地方执行,因此日志是:

// 1 23 / 05 / 2020 07:47:24
// 2 23 / 05 / 2020 07:47:24
// ^ Your test code finished executing, without waiting for the Get task
// Get 1 23 / 05 / 2020 07:47:24
// Get 2 23 / 05 / 2020 07:47:25

另外,await Task.Run(async () => await Get()) 也没有区别 和await Task.Run(Get) 就实际发生的情况而言。唯一的区别是,在第一个中,您正在创建另一个异步 lambda 函数来生成 Task,而您的 Get 方法已经是 Task,因此您可以直接使用它。

【讨论】:

    【解决方案2】:

    一般说明

    控制台不是学习 ot 以任何方式、形状或形式测试多任务处理的好环境。一个大问题是 MT 在不阻塞延续代码的情况下保持应用程序存活。在控制台中,我们必须手动执行此操作。 GUI 是正确的环境,因为它们是偶然的。 EventQueue 使应用程序保持活动状态,同时仍然允许 I/O 发生。

    Thread.Sleep() 不应在 Get 中使用。您应该改用更不可知的Task.Delay(1000)。在这里使用 Thread 类会导致不必要的副作用,甚至会破坏我们最初等待的原因。

    在 GUI 中不使用 Sleep 再试一次,因为它会得到更有意义的结果。

    什么是任务

    Task 只是一个有助于处理各种形式的多任务处理的结构。它的运行方式是“不可知的”。 Get() 可以使用 ThreadPools 异步执行。异步使用 async 和 await。只需调用RunSynchronously() 即可同步。或者通过从您手动启动的线程中调用RunSynchronously() 来异步调用。大概还有其他几种方式,我记不得了。

    不同类型的多任务处理

    多线程可用于实现多任务。从技术上讲,我们只需要 CPU 密集型工作的多线程,但在最长的时间里,它是实现 MT 的最便捷方式,所以我们倾向于使用它。很多。尤其是在不需要的情况下。

    即使完全理解我们这样做的原因,我认为我们过度使用滥用基于线程的多任务处理。尤其是图形用户界面,Multithreading causes some issues。不过,这是更简单的方法。所以很多东西,很多例子仍然是为基于线程的多任务设计的。

    直到最近,我们才获得 async 和 await 作为替代方案。 asyncawait 是一种无需恢复到多线程的多任务处理方式。我们总是可以并且仍然可以选择自己做这两个工作。但这是相当密集的代码并且容易出错。这两个在编译器和运行时之间很容易并且可靠地解决。所以只有现在,我们才开始回到无线程多任务的形式。

    Task.Run:

    “将指定的工作排入队列以在 ThreadPool 上运行并返回该工作的任务或任务句柄。” - https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.run

    所以 Run 接受一个任务,并通过 ThreadPool 执行它 - 一种基于线程的多任务形式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-01
      • 2022-01-07
      相关资源
      最近更新 更多