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;
}
}
}
答案 0 :(得分:3)
代码的结构表示DoExpensiveCalculation
是CPU绑定的操作。如果要在不占用CPU的情况下进行CPU约束的操作,则Thread.Sleep
是适当的选择。
我不确定是否可以将DoExpensiveCalculation换成Async方法,例如来自HttpClient的GetStringAsync而不出现问题。
嗯,那是完全不同的。 GetStringAsync
不是受CPU限制的操作;这是一个受I / O约束的操作。
与I / O绑定的操作自然是异步的,它们可以直接与async
和await
一起使用。与CPU绑定的操作自然是同步的,因此有时您需要使用Task.Run
。在这种情况下,“有时”通常表示“当您在UI线程上时”,以便在执行CPU绑定操作时不会冻结UI。将CPU绑定的操作包装在Task.Run
中后,可以将其视为异步操作,即await
从UI线程对其进行处理。
您的示例代码是一个控制台应用程序,通常不需要使用Task.Run
。控制台应用程序通常运行它们需要运行和退出的任何代码;在大多数情况下,不需要保持响应状态的UI,因此不需要Task.Run
。