我想在lambda表达式中调用异步方法。请帮我做下面的事情
例如 -
return xyz.Where(async x=> await AsyncMethodCall(x.val));
Async方法看起来像
public async Task<bool> AsyncMethodCall(Data d){...}
当我执行上述操作时,我收到以下错误
错误CS4010无法将异步lambda表达式转换为委托类型
'Func<Data, bool>'
。异步lambda表达式可能会返回void
,Task
或Task<T>
,其中任何一项均无法转换为'Func<Data, bool>'
。
提前感谢您的帮助
答案 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访问器将阻塞线程,直到方法调用完成。