.NET 4.6的Task.CompletedTask有什么作用?

63

4
意图更加清晰不足以吗? - svick
2
原因是您可以创建静态不可变任务,这些任务处于固定状态,从而节省内存。如果您需要返回已完成的任务,例如仅在必要时从网络下载内容并返回设置为已完成的虚拟任务,则等待您的任务的调用者可以立即继续执行。到目前为止,您需要创建自己的实例并缓存它,或通过TaskCompletionSource每次重新创建它。 - Alois Kraus
3
博客文章已经解释了为什么添加了Task.CompletedTask。它特别提到了"关心性能和避免分配的库代码"。现在将其与Task.FromResult(whatever)进行比较:它能避免分配吗?不,它不能。 - user743382
3个回答

61

Task.FromResult(whatever)适用于Task<TResult>,但在4.6之前,非泛型任务的没有类似的方法。您可以使用一个虚拟值和隐式转换为Task的方式来使用FromResult,但这会使意图有些不清晰(您并没有真正返回任何异步的),并且会在对象下方分配内存(而CompletedTask可以被缓存并共享给所有调用方)。

在当前的代码库中(4.5.2及更早版本),看到自定义静态完成任务并不罕见,因此我认为将其纳入框架本身是有意义的。


28

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();
    }
}

你指的是哪两个函数? - Orson
1
我现在明白它们是不同的例子。谢谢你澄清。 - Nae

-3
如果你想在一个类中等待一个函数,使用任务函数然后返回Task.CompletedTask。在函数定义中不需要使用async关键字。否则,你会写出一些奇怪的异步代码,比如await task.yield。
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);
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接