【问题标题】:Async Await in Lambda expression where clauseLambda 表达式 where 子句中的异步等待
【发布时间】:2017-10-10 13:25:09
【问题描述】:

我想在 lambda 表达式中调用一个异步方法。请帮我做以下事情

例如 -

return xyz.Where(async x=> await AsyncMethodCall(x.val));

Async 方法看起来像

public async Task<bool> AsyncMethodCall(Data d){...}

当我执行上述操作时,我收到以下错误

错误 CS4010 无法将异步 lambda 表达式转换为委托类型 'Func&lt;Data, bool&gt;'。异步 lambda 表达式可能返回 voidTaskTask&lt;T&gt;,都不能转换为'Func&lt;Data, bool&gt;'

提前感谢您的帮助

【问题讨论】:

  • 过滤器在哪里。它应该 filter 事物,而不是进行随机更改。为什么要在其中使用异步方法?您是否像使用 Select 语句一样使用它?
  • @PanagiotisKanavos 例如,它可以调用 Web 服务,或访问数据库......问题很好......你不能这样做,即使你可以也可能不会是个好主意,但这是另一个问题......
  • @xanatos 事实上这是一个坏主意,这可能是你不能这样做的原因,即为什么没有接受任务的Where() 方法
  • 一般asyncIEnumerable&lt;&gt;不要混用,因为Taskasync基础的类)预设了它包含的结果只有当它是Completed... 但是在这里你可以在Task 的生命周期“期间”枚举结果的各个部分(单个xyz 元素),而TaskCompleted,当有没有更多元素。
  • 您的 asyncawait 相互抵消。相同但更简单:.Where(x =&gt; AsyncMethodCall(x.val))。这应该会给你同样的错误,Where() 扩展方法不接受等待。

标签: c# .net linq asynchronous lambda


【解决方案1】:

异步序列很棘手,因为您确实必须考虑具体您希望代码做什么。

例如,您可能希望按顺序执行AsyncMethodCall 调用,然后返回所有结果:

var result = new List<T>();
foreach (var d in xyz)
  if (await AsyncMethodCall(d.val))
    result.Add(d);
return result;

或者,您可以同时执行所有 AsyncMethodCall 调用,然后收集并返回结果(同样,一次全部):

var tasks = xyz.Select(async d => new { d, filter = await AsyncMethodCall(d.val) });
var results = await Task.WhenAll(tasks);
return results.Where(x => x.filter).Select(x => x.d);

或者,您可以按顺序执行所有AsyncMethodCall 调用,并一次生成一个结果。这种方法与IEnumerable&lt;T&gt; 不兼容(假设您希望保持调用异步)。如果您想生成一个序列,其中AsyncMethodCall 在序列枚举期间被异步调用,那么您需要更改为IAsyncEnumerable&lt;T&gt;。如果您想生成由消费者启动的序列,然后自行生成结果,则需要更改为IObservable&lt;T&gt;

或者,您可以同时执行所有AsyncMethodCall 调用,并一次生成一个结果。这也与IEnumerable&lt;T&gt;不兼容;您需要更改为IObservable&lt;T&gt;。而且你还需要决定是保持原来的顺序,还是按照AsyncMethodCall完成的顺序生产它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-22
    • 2010-12-17
    • 1970-01-01
    • 1970-01-01
    • 2017-05-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多