[英]What are differences between the 3 calls for async Func<Task<T>> in c#?
What are differences between the 3 calls inside method WhatDifferences
?方法WhatDifferences
中的 3 个调用之间有什么区别?
Here is test code:这是测试代码:
async Task WhatDifferences(Context context)
{
await ActionAsync(context, async x => await IsOddAsync(x).ConfigureAwait(false));
await ActionAsync(context, x => IsOddAsync(x));
await ActionAsync(context, IsOddAsync);
}
async Task<T> ActionAsync<T>(Context context, Func<Context, Task<T>> action)
{
return await action(context).ConfigureAwait(false);
}
async Task<bool> IsOddAsync(Context context)
{
return await Task.Run(() => context.Count++ % 2 == 1).ConfigureAwait(false);
}
class Context
{
public int Count { get; set; }
}
I'm trying to decide which one to use in my codebase and based on my knowledge all 3 behave the same.我正在尝试决定在我的代码库中使用哪一个,并且根据我的知识,所有 3 个行为都相同。
The question is different with What's the method signature for passing an async delegate?问题与传递异步委托的方法签名不同?
You may know my concern if I show more logic如果我表现出更多的逻辑,你可能会知道我的担忧
async Task<T> ActionAsync<T>(Context context, Func<Context, Task<T>> action)
{
using (var transaction = new TransactionScope())
{
//do some async logic before action
var result = await action(context).ConfigureAwait(false);
//do other async validation logic after action
return result;
}
}
await
vs return Task
await
与返回Task
The difference between:和...之间的不同:
await ActionAsync(context, async x => await IsOddAsync(x).ConfigureAwait(false));
await ActionAsync(context, x => IsOddAsync(x));
In some cases you don't need the await
(and also not the async
of course)在某些情况下,您不需要await
(当然也不需要async
)
Methods that perform asynchronous operations don't need to use await if:在以下情况下,执行异步操作的方法不需要使用 await:
- There is only one asynchronous call inside the method方法内部只有一个异步调用
- The asynchronous call is at the end of the method异步调用在方法的最后
- Catching/handling exception that may happen within the Task is not necessary不需要捕获/处理任务中可能发生的异常
See Returning a Task without await .请参阅在没有等待的情况下返回任务。
In that case you could return the Task
intermediately.在这种情况下,您可以中间返回Task
。
Please note there is a small difference in behavior - depending on the implementation of IsOddAsync
:请注意,行为存在细微差别 - 取决于IsOddAsync
的实现:
Important: Returning the Task instead of awaiting it, changes the exception behavior of the method, as it won't throw the exception inside the method which starts the task but in the method which awaits it.重要提示:返回任务而不是等待它,会改变方法的异常行为,因为它不会在启动任务的方法中抛出异常,而是在等待它的方法中抛出异常。
As Gabriel Luci noted, with the current implementation of IsOddAsync
(one call and an await
), there is no difference in behavior.正如 Gabriel Luci 所指出的,使用IsOddAsync
的当前实现(一个调用和一个await
),行为没有区别。
x => IsOddAsync(x)
vs IsOddAsync
x => IsOddAsync(x)
与IsOddAsync
The difference between和...之间的不同
await ActionAsync(context, x => IsOddAsync(x));
await ActionAsync(context, IsOddAsync);
In the first one your are creating an anonymous (lambda) method with the parameter x
.在第一个中,您正在创建一个带有参数x
的匿名(lambda)方法。 As IsOddAsync
has also one parameter (with the same type), there is no need for the lambda method.由于IsOddAsync
也有一个参数(类型相同),因此不需要 lambda 方法。
Please note you need the lambda if IsOddAsync
has other parameters, eg and 2nd parameter, then you need the lambda.请注意您需要 lambda 如果IsOddAsync
有其他参数,例如和第二个参数,那么您需要 lambda。 Example:例子:
await ActionAsync(context, x => IsOddAsync(x, "mySecondParameter"));
In this case there is no difference in behavior, except the callstack when an exception in thrown inside.在这种情况下,行为没有区别,除了调用堆栈中抛出异常时。
I'm trying to decide which one to use in my codebase and based on my knowledge all 3 behave the same.我正在尝试决定在我的代码库中使用哪一个,并且根据我的知识,所有 3 个行为都相同。
In this specific instance, this is essentially true.在这个特定的例子中,这基本上是正确的。
This one creates a delegate that refers to the IsOddAsync
method:这个创建了一个引用IsOddAsync
方法的委托:
await ActionAsync(context, IsOddAsync);
This one creates a method for the lambda expression and the delegate refers to that compiler-generated method:这为 lambda 表达式创建了一个方法,并且委托引用了该编译器生成的方法:
await ActionAsync(context, x => IsOddAsync(x));
And this one does the same, but for an asynchronous lambda, so the compiler-generated method also has an async
state machine:和这个一样,但是对于一个异步 lambda,所以编译器生成的方法也有一个async
state 机器:
await ActionAsync(context, async x => await IsOddAsync(x).ConfigureAwait(false));
In general, your question boils down to two questions:一般来说,您的问题归结为两个问题:
async
/ await
or keep the keywords in?我应该省略async
/ await
还是保留关键字? This one is more nuanced.这个比较细致。 Eliding async
in this particular case is fine, because all the async
lambda is doing is calling a single method and passing its parameter.在这种特殊情况下删除async
很好,因为 lambda 所做的所有async
操作都是调用单个方法并传递其参数。 There's no possibility of exceptions being thrown from the lambda before or after the call to IsOddAsync
.在调用IsOddAsync
之前或之后,不可能从 lambda 引发异常。
However, if your lambda is more complex - doing operations on x
before passing it to IsOddAsync
, or doing operations on the result, or using a using
block, then you'd want to keep the async
/ await
keywords for maximum maintainability.但是,如果您的 lambda 更复杂 - 在将x
传递给IsOddAsync
之前对其进行操作,或者对结果进行操作,或者使用using
块,那么您需要保留async
/ await
关键字以获得最大的可维护性。 More information here .更多信息在这里。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.