我需要创建一个新的通用任务,该任务采用异步lambda,但不会立即启动。这就是为什么我不能使用Task.Run
,我想实例化一个新任务。我不能这样做,因为c#给了我下面的错误:
我的代码是无法将异步lambda表达式转换为委托类型
Func<int>
。异步lambda表达式可能返回void
,Task
或Task<T>
,但都不返回可转换为Func<int>
Task<int> task = new Task(async () => {
var number = await getNextNumber();
return await algorithm(number);
});
我需要创建一个新的通用任务,该任务采用异步lambda,但不会立即启动。这就是我不能使用Task的原因。运行并实例化一个新任务。
你永远不应该使用Task
构造函数,正如我在我的博客中所解释的。
在同步世界中,如果你想要一个可以稍后调用的对象来执行一些代码,你可以使用委托,例如Action
或Func<T>
。
在异步世界中,如果你想要一个可以稍后调用来执行某些代码的对象,你可以使用委托。异步lambda的委托类型与同步的不同,我在博客上解释过;所以你用Func<Task>
代替Action
,用Func<Task<T>>
代替Func<T>
。
Func<Task<int>> func = async () => {
var number = await getNextNumber();
return await algorithm(number);
};
...
int result = await func();
泛型任务类Task<T>
没有将Func<Task<T>>
作为参数的构造函数,因此不能用async关键字修饰lambda。然而,非泛型任务类Task
允许传入异步lambda。
一种解决方法是在Task<T>
类周围创建一个包装器,以使您也可以等待内部任务。
public class SuperTask<T>
{
private Task<T> task;
private Func<Task<T>> function;
public SuperTask(Func<Task<T>> function)
{
this.function = function;
}
public SuperTask<T> Start()
{
task = function();
return this;
}
public Task<T> AsTask() {
return task;
}
}
// And you can test it like so
SuperTask<int> testCase = new SuperTask<int>(async ()=> {
await Task.Delay(1000);
return 0;
});
int number = await testCase.Start().AsTask();
这个方法如何:
Task<int> task = new Task<int>(() =>
getNextNumber()
.ContinueWith(t => algorithm(t.Result))
.Unwrap()
.Result
);
好老的ContinueWith
加Unwrap
。
它看起来很丑,但应该可以工作。