Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

async lambda expression with arguments

Tags:

c#

async-await

I am trying to call my async function from a wrapper. But I am getting this compiler error. In the following code, I would like to get string x value with most of awaits abstracted/pushed into CallAsyncFunc code. What is the right way to do this in c# 4.5? Thanks!

error CS4010: Cannot convert async lambda expression to delegate type 'System.Func<int,string>'. An async lambda expression may return void, Task or Task<T>, none of which are convertible to 'System.Func<int,string>'.

public async Task<T2> CallAsyncFunc<T1,T2>(T1 a, Func<T1, T2> func)
{
    return func.Invoke(a);
}

public async Task<string> GetString(int value)
{
    await Task.Run(() => Thread.Sleep(2000));
    return "" + value;
}

public async Task MainAsyncEntry()
{
    string x = await CallAsyncFunc<int, string>(30, async(x) => await GetString(x));
}
like image 763
tvr Avatar asked Jan 09 '23 14:01

tvr


1 Answers

In:

string x = await CallAsyncFunc<int, string>(30, async(x) => await GetString(x));

You have two x that the first issue. Try:

string y = await CallAsyncFunc<int, string>(30, async(x) => await GetString(x));

Here the output of the lambda is string but because you use async it should be a Task or Task<T>.

You can write:

string y = await CallAsyncFunc<int, string>(30, x => GetString(x).Result);
// Equivalent to
string y = await CallAsyncFunc(30, x => GetString(x).Result);

Or

string y = await CallAsyncFunc<int, Task<string>>(30, x => GetString(x)).Result;
// Equivalent to
string y = await CallAsyncFunc(30, GetString).Result;

But in either cases, your CallAsyncFunc will run synchronously because it did not contain any await.

Here the good way to do it:

// This
public async Task<TOut> CallAsyncFunc<TIn, TOut>(TIn input, Func<TIn, Task<TOut>> func)
{
    return await func.Invoke(input);
}

// Or those
public Task<TOut> CallAsyncFunc<TIn, TOut>(TIn input, Func<TIn, Task<TOut>> func)
{
    return func.Invoke(input);
}

public async Task<string> GetString(int value)
{
    await Task.Run(() => Thread.Sleep(2000));
    return value.ToString(CultureInfo.InvariantCulture);
}

public async Task MainAsyncEntry()
{
    string y = await CallAsyncFunc(30, GetString);
}
like image 155
Orace Avatar answered Jan 17 '23 14:01

Orace