[英]async lambda expression with arguments
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. 在下面的代码中,我想得到
string x
值,大部分等待抽象/推入CallAsyncFunc
代码。 What is the right way to do this in c# 4.5? 在c#4.5中执行此操作的正确方法是什么? Thanks!
谢谢!
error CS4010: Cannot convert async lambda expression to delegate type '
System.Func<int,string>
'.错误CS4010:无法将异步lambda表达式转换为委托类型'
System.Func<int,string>
'。 An async lambda expression may returnvoid
,Task
orTask<T>
, none of which are convertible to 'System.Func<int,string>
'.异步lambda表达式可能返回
void
,Task
或Task<T>
,其中任何一个都不能转换为'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));
}
In: 在:
string x = await CallAsyncFunc<int, string>(30, async(x) => await GetString(x));
You have two x
that the first issue. 第一个问题你有两个
x
。 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>
. 这里lambda的输出是
string
但因为你使用async
它应该是一个Task
或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
. 但在任何一种情况下,您的
CallAsyncFunc
都将同步运行,因为它不包含任何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);
}
Remark 1: await GetString(x)
unwraps the Task<string>
to string
, then CallAsyncFunc
wraps again into Task<string>
. 备注1:
await GetString(x)
将Task<string>
CallAsyncFunc
包为string
,然后CallAsyncFunc
再次包装到Task<string>
。 You should rather keep the wrapped expression all the way long of your calling stack. 您应该将包装的表达式保持在调用堆栈的整个长度。 It is the recommanded way as far as I know.
据我所知,这是推荐的方式。
Remark 2: Resharper warns about CallAsyncFunc: 备注2:Resharper警告CallAsyncFunc:
This async method lacks ' await' operators and will run synchronously.
这种异步方法缺少“等待”运算符并将同步运行。 Consider using the 'await' operator to await non-blocking API calls, or ' await TaskEx.Run(…)' to do CPU-bound work on a background thread
考虑使用'await'运算符等待非阻塞API调用,或'await TaskEx.Run(...)'在后台线程上执行CPU绑定工作
Indeed you can ommit the async
keyword and avoid the re-wrapping into Task<string>
. 实际上,您可以省略
async
关键字并避免重新包装到Task<string>
。
As a result of Remark 1 and Remark 2, you could write following colde: 作为备注1和备注2的结果,您可以编写以下colde:
// REALLY ASYNC METHOD, WRAPS THE RESULT INTO Task<string>
public async Task<string> GetString(int value)
{
await Task.Run(() => Thread.Sleep(2000));
return "" + value;
}
// NOT ASYNC ANY MORE: DOES NOT WRAP THE RESULT INTO Task<T2> any more
public T2 CallAsyncFunc<T1, T2>(T1 a, Func<T1, T2> func)
{
return func.Invoke(a);
}
// WAIT FOR THE ASYNC RESULT ONLY IN THE OUTER SCOPE (UNWRAPS Task<string> BY THE WAY)
string y = await CallAsyncFunc(30, GetString);
string z = await CallAsyncFunc<int, Task<string>>(30, GetString);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.