Task.Run带有或不带有异步并等待

时间:2020-05-24 15:08:47

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

任何人都可以解释使用Task.Run或不使用async的区别,并等待下面的代码,例如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;
        }
    }

2 个答案:

答案 0 :(得分:2)

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

使用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,因此您可以直接使用它。

答案 1 :(得分:0)

一般说明

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

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

在没有睡眠的GUI中重试一次,因为它将为您带来更有意义的结果。

什么是任务

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

不同类型的多任务处理

多线程可用于实现多任务。从技术上讲,我们只需要具有CPU限制工作的多线程,但是在最长的时间里,它通常是实现MT的最方便的方法,因此我们倾向于使用它。很多。尤其是在不必要的情况下。

即使完全理解我们为什么这么做,我认为我们过度使用滥用基于线程的多任务处理。特别是对于GUI,Multithreading causes some issues。不过,这是更简单的方法。因此,很多事情仍然为基于线程的多任务处理而设计。

直到最近,我们才获得异步并等待替代。 asyncawait是一种多任务处理方式,无需还原到Mutlthreading。我们一直有并且仍然可以选择自己做这两个工作。但是,这需要大量代码,并且容易出错。两者很容易,并且在编译器和运行时之间可以可靠地解决。所以只有现在,我们才开始回到无线程多任务的形式。

Task.Run

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

因此,Run执行一项任务,并通过ThreadPool(基于Thread的muttiasking的一种形式)执行该任务。