Async Await在Lambda表达式where子句中

时间:2017-05-11 13:40:33

标签: c# .net linq asynchronous lambda

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

例如 -

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

Async方法看起来像

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

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

  

错误CS4010无法将异步lambda表达式转换为委托类型   'Func<Data, bool>'。异步lambda表达式可能会返回voidTask   或Task<T>,其中任何一项均无法转换为'Func<Data, bool>'

提前感谢您的帮助

2 个答案:

答案 0 :(得分:11)

异步序列很棘手,因为你真的必须考虑你希望代码做什么

例如,您可能希望按顺序执行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<T>不兼容(假设您要保持调用异步)。如果要生成在序列枚举期间异步调用AsyncMethodCall的序列,则需要更改为IAsyncEnumerable<T>。如果您想要由消费者生成启动的序列,然后自己生成结果,则需要更改为IObservable<T>

或者,您可以同时执行所有AsyncMethodCall个调用,并一次生成一个结果。这也与IEnumerable<T>不兼容;您需要更改为IObservable<T>。您还需要决定是保持原始排序,还是按AsyncMethodCall完成顺序生成它们。

答案 1 :(得分:-1)

你在做什么是行不通的。原因从错误消息中可以清楚地看出:

  

错误CS4010无法将异步lambda表达式转换为委托类型   “功能”。异步lambda表达式可能返回void,Task   或任务,其中任何一个都不能转换为'Func'。

你有一个lambda表达式吐出Task<bool>Where()函数需要一个Function委托。您无法将Task转换为可用于获取bool的Function委托。故事结束。

如果你真的想以这种方式调用方法,你需要确保lambda返回一个bool,在这种情况下,是调用异步方法的结果:

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

这将起作用并给你有意义的结果,因为调用Result访问器将阻塞线程,直到方法调用完成。