等待或Task.FromResult [英] Await or Task.FromResult
问题描述
我有一项服务可以说,
public interface ISomeService
{
Task<bool> DoSomeExpensiveCheckAsync(string parameter);
}
我有此类可以使用该服务。它只需要做一些简单的空检查,然后返回服务响应即可。
And I have this class to consume the service. It just needs to do some simple null checks and then return the service response back.
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);
}
}
我应该做 DoSomething1Async
或 DoSomething2Async
?
根据这个答案,我不应该用不必要的 await
换行,但是我必须使用 Task .FromResult(false)
用于短路,如 DoSomething2Async
According to this answer, I should not wrap with an unnecessary await
but then I have to use Task.FromResult(false)
for shortcircuiting as in DoSomething2Async
,但根据此答案有时会出现 try / catch
和使用
语句,实际上我应该在返回之前先等待
。
But according to this answer there are cases with try/catch
and using
statements where I actually should await
before returning.
我纠正了然后说,
-
如果我必须使用
try / catch
或使用
,那么我应该等待
否则,如果您仅打算返回,请不要等待
。并使用 Task.FromResult
进行短路
Otherwise do not await
if you are only going to return. And use Task.FromResult
for short circuiting
我喜欢 DoSomething1Async
更多,并且如果有人说没关系,想在任何地方都可以这样做:)。
I like DoSomething1Async
more, and want to do that everywhere if someone says it doesnt matter :).
推荐答案
如果您担心它,请缓存 Task
:
If you're worried about it, cache the Task
:
static readonly Task<bool> falseTask = Task.FromResult(false);
async
关键字还将异常包裹起来返回的 Task
以及正确的堆栈跟踪。这是权衡的行为,是行为的安全性。
The async
keyword also wraps exceptions up in the returned Task
, along with a proper stack trace. It's a tradeoff, safety of behavior for perf.
让我们看一下每个场景都不同的不同场景:
Lets look at the difference scenarios where each would be different:
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;
}
此处仅说明了这一点- IsNullOrWhiteSpace
实际上不会因任何原因引发任何异常。
Just illustrating the point here -- IsNullOrWhiteSpace
does not actually throw any exceptions for any reason.
就堆栈跟踪而言,异步堆栈跟踪取决于您等待
。没有 await
表示该方法将从堆栈跟踪中消失。
As far as stack traces go, async stack traces are determined by where you await
. No await
means the method will disappear from the stack trace.
说 DoSomeExpensiveCheckAsync
引发异常。在 DoSomething1Async
的情况下,堆栈跟踪看起来像 caller->。 DoSomething1Async-> DoSomeExpensiveCheckAsync
。
Say DoSomeExpensiveCheckAsync
throws an exception. In the case of DoSomething1Async
, the stack trace will look like caller -> DoSomething1Async -> DoSomeExpensiveCheckAsync
.
对于 DoSomething2Async
,堆栈跟踪看起来像 caller-> DoSomeExpensiveCheckAsync
。
In the case of DoSomething2Async
, the stack trace would look like caller -> DoSomeExpensiveCheckAsync
. Depending on the complexity of your code, this can make things difficult to debug.
实际上,我一般只会直接返回 Task > code>如果我不知道会在其之前引发任何异常,并且方法名仅仅是一个重载,则转发给另一个重载。此规则总是有例外,肯定有一些您想最大化性能的地方。只需仔细选择,就可以意识到您可能会使您和您的用户的生活变得更加艰难。
In practice, I will generally only directly return a Task
if I knew no exceptions would be thrown prior to it, and if the method name was merely an overload forwarding to another overload. There are always exceptions to this rule, there are bound to be places you want to maximize performance. Just pick and choose carefully, realize you might be making the life of you and your user harder.
这篇关于等待或Task.FromResult的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!