Task.CompleteTask和Task.FromResult
问题描述 |
实现接口中的异步方法时,因为返回值类型是Task或Task<T>,所以即使方法的具体实现逻辑极简执行极快(比如直接返回一个常量字符串),我们可能也需要被迫新建一个Task去执行,如下:
public interface IComputer
{
Task Do();
Task<string> DoString();
}
public class MyComputer : IComputer
{
public Task Do()
{
//return Task.Run(() => { Console.WriteLine("逻辑很简单执行很快的代码块,新建一个任务或线程得不偿失,反而损伤性能。"); });
return Task.Run<string>(() => "逻辑很简单执行很快的代码块,新建一个任务或线程得不偿失,反而损伤性能。");
}
public async Task<string> DoString()
{
//return Task.Run<string>(() => "逻辑很简单执行很快的代码块,新建一个任务或线程得不偿失,反而损伤性能。");
return await Task.Run<string>(() => "逻辑很简单执行很快的代码块,新建一个任务或线程得不偿失,反而损伤性能。");
}
}
上述实现的缺点 |
开一个Task去执行简单的逻辑会新增开销(构造Task实例,Task排队,线程和上下文切换,回调索取结果,Task状态运转维护等),还不如在当前线程和上下文直接运行划算。
优化手段 |
可以使用Task.CompletedTask和Task.FromResult优化,二者表示一个已经完成的Task实例,不会产生上下文切换,任务队列排队,回调索取结果等,甚至Task实例都是从缓存中直接返回而不需新建。在满足接口返回形式的前提下,又保证了高性能。
public class MyComputer : IComputer
{
public Task Do()
{
// return Task.FromResult("Hello New Boy");
return Task.CompletedTask;
}
public Task<string> DoString()
{
return Task.FromResult("Hello New Boy");
}
}