这篇博客文章提到了新的任务API,包括在.NET 4.6中引入的Task.CompletedTask属性。
为什么要添加这个?与Task.FromResult(whatever)
相比有何优势?
这篇博客文章提到了新的任务API,包括在.NET 4.6中引入的Task.CompletedTask属性。
为什么要添加这个?与Task.FromResult(whatever)
相比有何优势?
Task.FromResult(whatever)
适用于Task<TResult>
,但在4.6之前,非泛型任务的没有类似的方法。您可以使用一个虚拟值和隐式转换为Task
的方式来使用FromResult
,但这会使意图有些不清晰(您并没有真正返回任何异步的值),并且会在对象下方分配内存(而CompletedTask
可以被缓存并共享给所有调用方)。
在当前的代码库中(4.5.2及更早版本),看到自定义静态完成任务并不罕见,因此我认为将其纳入框架本身是有意义的。
Task.CompletedTask
属性在需要给调用者一个已经完成的虚拟任务(不返回值/结果)时非常重要。这可能是为了满足“接口”合同或测试目的。
Task.FromResult(data)
也返回一个虚拟任务,但这次是带有数据或结果的。您可能会这样做,因为您已经拥有这些数据,没有必要执行任何操作来获取它。
示例 - Task.CompletedTask
public Task DoSomethingAsync()
{
return Task.CompletedTask; // null would throw exception on await
}
例子 - Task.FromResult(data)
public Task<User> GetUserAsync()
{
if(cachedUser != null)
{
return Task.FromResult(cachedUser);
}
else
{
return GetUserFromDb();
}
}
public class TaskCustom
{
public Task Function1Async(ITestOutputHelper output)
{
for (int i = 0; i < 10; i++)
{
output.WriteLine("reached fnc1 "+i.ToString());
}
return Task.CompletedTask; // null would throw exception on await
}
public Task Function2Async(ITestOutputHelper output)
{
for (int i = 0; i < 10; i++)
{
output.WriteLine("reached fnc2 " + i.ToString());
}
return Task.CompletedTask; // null would throw exception on await
}
}
public async Task TaskTestCompletedTask()
{
TaskCustom obj = new TaskCustom();
await obj.Function1Async(output);
await obj.Function2Async(output);
Assert.True(true);
}
Task.CompletedTask
。它特别提到了"关心性能和避免分配的库代码"。现在将其与Task.FromResult(whatever)
进行比较:它能避免分配吗?不,它不能。 - user743382