如何使用异步模拟昂贵的操作?

时间:2019-01-23 15:50:10

标签: c# .net-core async-await console-application

this page中的代码真的是模拟长时间运行的任务的最佳方法吗?

我研究过的控制台应用程序非常简单,并且似乎可以正常工作。

我不确定是否可以将DoExpensiveCalculation换成Async的方法,如GetStringAsync中的HttpClient,而不会出现问题。

using System;
using System.Threading.Tasks;

namespace ExpensiveAsync
{
    public class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("started");

            var t = CalculateResult("stuff and that");

            Console.WriteLine("press return");
            Console.ReadLine();
        }

        public static async Task<string> CalculateResult(string data)
        {
            // This queues up the work on the threadpool.
            var expensiveResultTask = Task.Run(() => DoExpensiveCalculation(data));

            // Note that at this point, you can do some other work concurrently,
            // as CalculateResult() is still executing!

            Console.WriteLine("concurrent");

            // Execution of CalculateResult is yielded here!
            var result = await expensiveResultTask; // CalculateResult returns the Task object here

            Console.WriteLine("synchronous"); // this code runs once the DoExpensiveCalculation method has finished

            return result;
        }

        public static string DoExpensiveCalculation(string data)
        {
            var completionTime = DateTime.Now.AddSeconds(3);

            Console.WriteLine("begin");

            while (DateTime.Now < completionTime) ;

            Console.WriteLine("finish");

            return data;
        }
    }
}

1 个答案:

答案 0 :(得分:3)

代码的结构表示DoExpensiveCalculation是CPU绑定的操作。如果要在不占用CPU的情况下进行CPU约束的操作,则Thread.Sleep是适当的选择。

  

我不确定是否可以将DoExpensiveCalculation换成Async方法,例如来自HttpClient的GetStringAsync而不出现问题。

嗯,那是完全不同的。 GetStringAsync不是受CPU限制的操作;这是一个受I / O约束的操作。

与I / O绑定的操作自然是异步的,它们可以直接与asyncawait一起使用。与CPU绑定的操作自然是同步的,因此有时您需要使用Task.Run。在这种情况下,“有时”通常表示“当您在UI线程上时”,以便在执行CPU绑定操作时不会冻结UI。将CPU绑定的操作包装在Task.Run中后,可以将其视为异步操作,即await从UI线程对其进行处理。

您的示例代码是一个控制台应用程序,通常不需要使用Task.Run。控制台应用程序通常运行它们需要运行和退出的任何代码;在大多数情况下,不需要保持响应状态的UI,因此不需要Task.Run