在将方法调用传递给另一个异步方法时,调用方方法是否也应该异步并使用await,还是我应该简单地传递它从被调用方收到的Task?如果调用方法进行了更多的准备,该怎么办?
public Task<Message> Unsubscribe(int subscriptionId, CancellationToken cancellationToken)
{
var data = new MessageData
{
["subscriptionId"] = subscriptionId
};
return SendAsync(OpCode.Unsubscribe, data, cancellationToken);
}
public Task<Message> Unsubscribe(int subscriptionId) =>
Unsubscribe(subscriptionId, CancellationToken.None);
SendAsync
是异步的,并返回Task<Message>
。因此,Unsubscribe
的第一个重载应该像上面这样或那样:
public async Task<Message> Unsubscribe(int subscriptionId, CancellationToken cancellationToken)
{
var data = new MessageData
{
["subscriptionId"] = subscriptionId
};
return await SendAsync(OpCode.Unsubscribe, data, cancellationToken);
}
另一种选择是使用Unsubscribe
的第二个重载。可能像上面这样:
public async Task<Message> Unsubscribe(int subscriptionId) =>
await Unsubscribe(subscriptionId, CancellationToken.None);
我猜想更多的异步和等待会增加编译器引入的复杂性(我在堆栈跟踪中看到了它!),并且可能会降低性能和内存消耗。但是至少它应该提供一致的异常传播。
答案 0 :(得分:2)
在您引用的示例中,只返回任务而无需await
很好(并且可以说是更好的选择),但这确实需要格外小心。
一旦遇到麻烦,就是在Task
块中处理using
时。这些行为可能有很大不同:
public async Task<Something> AwaitTheTask()
{
using (var someResource = GetAResource())
{
return await SomeAsyncThing(someResource);
}
}
public Task<Something> DontAwaitTheTask()
{
using (var someResource = GetAResource())
{
return SomeAsyncThing(someResource);
}
}
在第一个示例中,using
块将不会处置someResource
,直到等待的Task
完成。在第二个示例中,someResource
将被立即处置,很可能导致需要该资源的代码出现问题。