lab*_*roo 20 .net c# task-parallel-library async-await
我有一个服务可以说,
public interface ISomeService
{
Task<bool> DoSomeExpensiveCheckAsync(string parameter);
}
Run Code Online (Sandbox Code Playgroud)
我有这个课程来消费服务.它只需要做一些简单的空检查,然后返回服务响应.
public class SomeServiceConsumer
{
private readonly ISomeService _serviceClient;
public SomeServiceConsumer(ISomeService serviceClient)
{
_serviceClient = serviceClient;
}
public async Task<bool> DoSomething1Async(string someParameter)
{
if (string.IsNullOrWhiteSpace(someParameter))
{
return false;
}
return await _serviceClient.DoSomeExpensiveCheckAsync(someParameter);
}
//No async or await keywords
public Task<bool> DoSomething2Async(string someParameter)
{
if (string.IsNullOrWhiteSpace(someParameter))
{
return Task.FromResult(false);
}
return _serviceClient.DoSomeExpensiveCheckAsync(someParameter);
}
}
Run Code Online (Sandbox Code Playgroud)
我应该做的DoSomething1Async还是DoSomething2Async?
根据这个答案,我不应该用不必要的东西包裹await但是我必须Task.FromResult(false)用于短路DoSomething2Async
但根据这个答案,有一些案例try/catch和using陈述,我实际上应该await在返回之前.
我当时说的是正确的
如果我必须使用try/catch或using我应该await
await如果你只是要返回,否则不要.并Task.FromResult用于短路
我DoSomething1Async更喜欢,如果有人说这无关紧要,我想在任何地方都这样做.
Cor*_*son 17
如果你担心它,请缓存Task:
static readonly Task<bool> falseTask = Task.FromResult(false);
Run Code Online (Sandbox Code Playgroud)
该async关键字还会在返回的内容中包含异常Task以及正确的堆栈跟踪.这是权衡行为的安全性.
让我们看看每种情况会有所不同的差异情景:
async Task UseSomething1Async(string someParameter)
{
// if IsNullOrWhiteSpace throws an exception, it will be wrapped in
// the task and not thrown here.
Task t1 = DoSomething1Async(someParameter);
// rather, it'll get thrown here. this is best practice,
// it's what users of Task-returning methods expect.
await t1;
// if IsNullOrWhiteSpace throws an exception, it will
// be thrown here. users will not expect this.
Task t2 = DoSomething2Async(someParameter);
// this would never have been reached.
await t2;
}
Run Code Online (Sandbox Code Playgroud)
只是在这里说明一点 - IsNullOrWhiteSpace实际上并没有因任何原因抛出任何异常.
就堆栈跟踪而言,异步堆栈跟踪由您所在的位置决定await.No await表示该方法将从堆栈跟踪中消失.
Say DoSomeExpensiveCheckAsync抛出异常.在这种情况下DoSomething1Async,堆栈跟踪看起来像caller -> DoSomething1Async -> DoSomeExpensiveCheckAsync.
在这种情况下DoSomething2Async,堆栈跟踪看起来像caller -> DoSomeExpensiveCheckAsync.根据代码的复杂程度,这可能会使调试变得困难.
在实践中,我通常只会直接返回一个Task如果我知道在它之前不会抛出异常,并且如果方法名称仅仅是转发到另一个重载的过载.这条规则总有例外,你必须要有最大化性能的地方.只需仔细挑选,即可意识到您可能会让您和您的用户的生活更加艰难.