如何使用async lambda作为参数创建一个新的泛型Task



我需要创建一个新的通用任务,该任务采用异步lambda,但不会立即启动。这就是为什么我不能使用Task.Run,我想实例化一个新任务。我不能这样做,因为c#给了我下面的错误:

无法将异步lambda表达式转换为委托类型Func<int>。异步lambda表达式可能返回void,TaskTask<T>,但都不返回可转换为Func<int>

我的代码是
Task<int> task = new Task(async () => {
var number = await getNextNumber();
return await algorithm(number);
});

我需要创建一个新的通用任务,该任务采用异步lambda,但不会立即启动。这就是我不能使用Task的原因。运行并实例化一个新任务。

你永远不应该使用Task构造函数,正如我在我的博客中所解释的。

在同步世界中,如果你想要一个可以稍后调用的对象来执行一些代码,你可以使用委托,例如ActionFunc<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
);

好老的ContinueWithUnwrap

它看起来很丑,但应该可以工作。

相关内容

  • 没有找到相关文章

最新更新