我有一个包含两个方法的类,Load()和Process()。我希望能够将这些单独作为后台任务或按顺序运行。我喜欢ContinueWith()语法,但我无法让它工作。我必须在我继续的方法上获取一个Task参数,并且在初始方法上不能有Task参数。
我想在没有lambda表达式的情况下执行此操作,但我是否使用它们,在其中一个方法上强制执行任务参数,或者创建第三个方法LoadAndProcess()?
void Run()
{
// doesn't work, but I'd like to do it
//Task.Factory.StartNew(MethodNoArguments).ContinueWith(MethodNoArguments);
Console.WriteLine("ContinueWith");
Task.Factory.StartNew(MethodNoArguments).ContinueWith(MethodWithTaskArgument).Wait();
Console.WriteLine("Lambda");
Task.Factory.StartNew(() => { MethodNoArguments(); MethodNoArguments(); }).Wait();
Console.WriteLine("ContinueWith Lambda");
Task.Factory.StartNew(MethodNoArguments).ContinueWith(x => {
MethodNoArguments();
}).Wait();
}
void MethodNoArguments()
{
Console.WriteLine("MethodNoArguments()");
}
void MethodWithTaskArgument(Task t = null)
{
Console.WriteLine("MethodWithTaskArgument()");
}
答案 0 :(得分:14)
在ContinueWith()
的所有重载中,第一个参数是一个带Task
的委托,因此您无法将无参数委托传递给它。
我认为使用lambdas非常好,并且不会影响可读性。代码中的lambda不必要地冗长:
Task.Factory.StartNew(MethodNoArguments).ContinueWith(_ => MethodNoArguments())
或者,正如Cory Carson在评论中指出的那样,你可以写一个扩展方法:
public static Task ContinueWith(this Task task, Action action)
{
return task.ContinueWith(_ => action());
}
答案 1 :(得分:4)
使用多个continuation时编写干净的代码并不容易,尽管您可以遵循一些规则来使代码更清晰:
您可以将代码更改为更简洁的代码:
var call1=Task.Factory.StartNew(()=>MethodNoArguments());
var call2 = call1.ContinueWith(_ => MethodNoArguments());
call2.Wait();
甚至
var call1 = Task.Factory.StartNew<Task>(MethodNoArguments);
var call2 = call1.Then(MethodNoArguments);
call2.Wait();
Stephen Toub讨论了Then扩展以及其他可以在Processing Sequences of Asynchronous Operations with Tasks
中清理代码的方法这个问题在C#4中得到了很好的解决。在C#5中,您可以使用async / await关键字创建看起来像原始同步版本的干净代码,例如:
static async Task Run()
{
await MethodNoArguments();
await MethodNoArguments();
}
static async Task MethodNoArguments()
{
await Task.Run(()=>Console.WriteLine("MethodNoArguments()"));
}
Visual Studio 11和.NET 4.5具有Go Live许可证,因此您可以立即开始使用它们。
您可以使用C#4中的Async CTP来获得相同的结果。您可以在生产中使用Async CTP,因为它具有go live许可证。缺点是,由于CTP和.NET 4.5之间的差异(例如,CTP具有TaskEx.Run而不是Task.Run),当您转移到.NET 4.5时,您将不得不对代码进行一些小的更改。 p>