1

I am getting an error with the following code.

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

This method calls the following function

private async Task<bool> FlushUrlAsync(bool recursive, string memoryCacheUrl)
{
    return await someMagic(); //for clearity I removed the code.
}

It looks a lot like: Convert async lambda expression to delegate type System.Func<T>?, howevery, there solution won't /can't get it to work for me.

I had:

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;

Then resharper gave me the code that is provided, but just adding the async keyword doesn't work.

.Aggregate(true, async (current, memoryCacheUrl) => current && await FlushUrlAsync(recursive, memoryCacheUrl));

will give me the erorr: the return type of async method must be void, task or Task.

any ideas?

2 Answers 2

4

I would personally use the foreach implementation, but answering the concrete question.

Without async the Aggregate overload used has the following signature:

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

Note the func parameter - it's a method receiving bool and string returning a bool. The important part is that the type of the first argument is the same as the type of the result, as well as the type of seed parameter.

Since async lambda must return a Task derived object. You need a bool result, so let substitute it with Task<bool>:

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

which leads to the following solution:

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));
Sign up to request clarification or add additional context in comments.

1 Comment

perfect! but i have to agree.... using the foreach makes it more readable.
0

Use ContinueWith with 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;
            };

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.