我得到一个错误与以下代码。
public async Task<bool> FlushUrlAsync(Uri url, bool recursive, CancellationToken token = default(CancellationToken))
{
_serverPortsConfig.CacheServerPorts
.Select(cacheServerPort => $"http://{url.Host}:{cacheServerPort}{url.AbsolutePath}")
.Aggregate(true, (current, memoryCacheUrl) => current && await FlushUrlAsync(recursive, memoryCacheUrl)); //<--- produces the next error:
// Cannot convert async lambda expression to delegate type
// 'Func<bool, string, bool>'. An async lambda expression may return
// void, Task or Task<T>, none of which are convertible to
// 'Func<bool, string, bool>'.
}
这个方法调用以下函数
private async Task<bool> FlushUrlAsync(bool recursive, string memoryCacheUrl)
{
return await someMagic(); //for clearity I removed the code.
}
它看起来很像:将异步lambda表达式转换为委托类型System.Func
var result = true;
foreach (var cacheServerPort in _serverPortsConfig.CacheServerPorts)
{
var memoryCacheUrl = $"http://{url.Host}:{cacheServerPort}{url.AbsolutePath}";
result = result && await FlushUrlAsync(memoryCacheUrl, recursive);
}
return result;
然后resharper给了我提供的代码,但是仅仅添加async关键字是不行的。
.Aggregate(true, async (current, memoryCacheUrl) => current && await FlushUrlAsync(recursive, memoryCacheUrl));
将给我错误:async方法的返回类型必须是void, task或task。
任何想法?
我个人将使用foreach
实现,但回答具体问题。
如果没有async
,使用的Aggregate
过载具有以下特征:
bool Aggregate<bool, string>(bool seed, Func<bool, string, bool> func)
注意func
参数-它是一个接收bool
和string
返回bool
的方法。重要的是,第一个实参的类型与结果的类型以及seed
形参的类型相同。
因为async
lambda必须返回Task
的派生对象。您需要bool
的结果,所以让我们将其替换为Task<bool>
:
Task<bool> Aggregate<bool, string>(Task<bool> seed, Func<Task<bool>, string, Task<bool>> func)
,导致以下解决方案:
return await _serverPortsConfig.CacheServerPorts
.Select(cacheServerPort => $"http://{url.Host}:{cacheServerPort}{url.AbsolutePath}")
.Aggregate(Task.FromResult(true), async (current, memoryCacheUrl) =>
await current && await FlushUrlAsync(recursive, memoryCacheUrl));
使用ContinueWith和TaskContinuationOptions,
Func<Exception, bool> handlerFunc = (Exception ex) =>
{
ex.HandleExceptionAsync().ContinueWith(async (result) =>
{
// all await operations can be called here
}, System.Threading.Tasks.TaskContinuationOptions.OnlyOnRanToCompletion);
return true;
};