【问题标题】:Cannot convert async lambda expression to delegate type 'Func<bool, string, bool>'无法将异步 lambda 表达式转换为委托类型 'Func<bool, string, bool>'
【发布时间】:2016-10-27 08:29:51
【问题描述】:

我收到以下代码错误。

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.
}

看起来很像:Convert async lambda expression to delegate type System.Func<T>?,但是,那里的解决方案不会/无法让它为我工作。

我有:

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。

有什么想法吗?

【问题讨论】:

    标签: c# asynchronous lambda


    【解决方案1】:

    我个人会使用foreach 实现,但要回答具体问题。

    如果没有 async,使用的 Aggregate 重载具有以下签名:

    bool Aggregate<bool, string>(bool seed, Func<bool, string, bool> func)
    

    注意func 参数 - 这是一个接收boolstring 返回bool 的方法。重要的部分是第一个参数的类型与结果的类型相同,以及seed参数的类型。

    由于async lambda 必须返回一个Task 派生对象。你需要一个bool 结果,所以用Task&lt;bool&gt; 代替它:

    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));
    

    【讨论】:

    • 完美!但我必须同意....使用 foreach 使其更具可读性。
    【解决方案2】:

    将 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;
                };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多