![](/img/trans.png)
[英]What's the difference between the following Func<Task<T>> async delegate approaches?
[英]What are differences between the 3 calls for async Func<Task<T>> in c#?
方法WhatDifferences
中的 3 个调用之间有什么区别?
这是测试代码:
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; }
}
我正在尝试决定在我的代码库中使用哪一个,并且根据我的知识,所有 3 个行为都相同。
如果我表现出更多的逻辑,你可能会知道我的担忧
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
与返回Task
和...之间的不同:
await ActionAsync(context, async x => await IsOddAsync(x).ConfigureAwait(false));
await ActionAsync(context, x => IsOddAsync(x));
在某些情况下,您不需要await
(当然也不需要async
)
在以下情况下,执行异步操作的方法不需要使用 await:
- 方法内部只有一个异步调用
- 异步调用在方法的最后
- 不需要捕获/处理任务中可能发生的异常
请参阅在没有等待的情况下返回任务。
在这种情况下,您可以中间返回Task
。
请注意,行为存在细微差别 - 取决于IsOddAsync
的实现:
重要提示:返回任务而不是等待它,会改变方法的异常行为,因为它不会在启动任务的方法中抛出异常,而是在等待它的方法中抛出异常。
正如 Gabriel Luci 所指出的,使用IsOddAsync
的当前实现(一个调用和一个await
),行为没有区别。
x => IsOddAsync(x)
与IsOddAsync
和...之间的不同
await ActionAsync(context, x => IsOddAsync(x));
await ActionAsync(context, IsOddAsync);
在第一个中,您正在创建一个带有参数x
的匿名(lambda)方法。 由于IsOddAsync
也有一个参数(类型相同),因此不需要 lambda 方法。
请注意您需要 lambda 如果IsOddAsync
有其他参数,例如和第二个参数,那么您需要 lambda。 例子:
await ActionAsync(context, x => IsOddAsync(x, "mySecondParameter"));
在这种情况下,行为没有区别,除了调用堆栈中抛出异常时。
我正在尝试决定在我的代码库中使用哪一个,并且根据我的知识,所有 3 个行为都相同。
在这个特定的例子中,这基本上是正确的。
这个创建了一个引用IsOddAsync
方法的委托:
await ActionAsync(context, IsOddAsync);
这为 lambda 表达式创建了一个方法,并且委托引用了该编译器生成的方法:
await ActionAsync(context, x => IsOddAsync(x));
和这个一样,但是对于一个异步 lambda,所以编译器生成的方法也有一个async
state 机器:
await ActionAsync(context, async x => await IsOddAsync(x).ConfigureAwait(false));
一般来说,您的问题归结为两个问题:
async
/ await
还是保留关键字? 这个比较细致。 在这种特殊情况下删除async
很好,因为 lambda 所做的所有async
操作都是调用单个方法并传递其参数。 在调用IsOddAsync
之前或之后,不可能从 lambda 引发异常。
但是,如果您的 lambda 更复杂 - 在将x
传递给IsOddAsync
之前对其进行操作,或者对结果进行操作,或者使用using
块,那么您需要保留async
/ await
关键字以获得最大的可维护性。 更多信息在这里。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.