任务链(等待上一个任务完成)
var tasks = new List(); foreach (var guid in guids) { var task = new Task( ...); tasks.Add(task); } foreach (var task in tasks) { task.Start(); Task.WaitAll(task); }
这是UI线程的运行。 我需要一个接一个地执行任务变量中的所有任务。 问题是如果我调用Task.WaitAll(任务),UI冻结。 如果没有UI冻结,我该如何做以下逻辑?
这不是任务链。
您需要使用ContinueWith
进行任务链接。 上一个任务需要更新UI。
Task.Factory.StartNew( () => DoThis()) .ContinueWith((t1) => DoThat()) .ContinueWith((t2) => UpdateUi(), TaskScheduler.FromCurrentSynchronizationContext());
注意最后一行有TaskScheduler.FromCurrentSynchronizationContext()
这将确保任务将在同步上下文(UI线程)中运行。
最好的方法是使用任务并行库(TPL)和Continuations 。 延续不仅允许您创建任务流,还可以处理您的exception。 这是对TPL的一个很好的介绍 。 但是要给你一些想法……
您可以使用启动TPL任务
Task task = Task.Factory.StartNew(() => { // Do some work here... });
现在,当先前任务完成(错误或成功)时,您可以使用ContinueWith
方法启动第二个任务
Task task1 = Task.Factory.StartNew(() => Console.WriteLine("Antecedant Task")); Task task2 = task1.ContinueWith(antTask => Console.WriteLine("Continuation..."));
因此,只要task1
完成,失败或被取消, task2
‘就会启动’并开始运行。 请注意,如果task1
在到达第二行代码之前已完成,则task2
将被安排立即执行。 传递给第二个lambda的antTask
参数是对前一个任务的引用。 有关详细示例,请参阅此链接 …
您还可以传递先行任务的延续结果
Task.Factory.StartNew(() => 1) .ContinueWith(antTask => antTask.Result * 4) .ContinueWith(antTask => antTask.Result * 4) .ContinueWith(antTask =>Console.WriteLine(antTask.Result * 4)); // Prints 64.
注意。 请务必在提供的第一个链接中阅读exception处理,因为这会导致TPL的新手误入歧途。
最后要特别注意你想要的是儿童任务。 子任务是创建为AttachedToParent
任务。 在这种情况下,在所有子任务完成之前,延续不会运行
TaskCreationOptions atp = TaskCreationOptions.AttachedToParent; Task.Factory.StartNew(() => { Task.Factory.StartNew(() => { SomeMethod() }, atp); Task.Factory.StartNew(() => { SomeOtherMethod() }, atp); }).ContinueWith( cont => { Console.WriteLine("Finished!") });
我希望这有帮助。
你需要使用Continorations:
lastTask.ContinueWith(() => newTask.Start());