我使用条件延续构建了一小组任务,但是我遇到了一些令人厌烦的行为。 我的链看起来像这样:
LoadSettings (OnlyOnFaulted)-> ErrorHandler (none)-> Cleanup (none)-> Exit
| (OnlyOnRanToCompletion)
CheckForUpdates (OnlyOnFaulted)-> ErrorHandler (none)-> Cleanup (none)-> Exit
| (OnlyOnRanToCompletion)
Update (OnlyOnFaulted)-> ErrorHandler (none)-> Cleanup (none)-> Exit
| (OnlyOnRanToCompletion)
Cleanup (OnlyOnFaulted)-> ErrorHandler (none)-> Exit
| (OnlyOnRanToCompletion)
Exit
据我所知,这个链应该异步运行(即不在ui线程中)但是一个接一个地运行(所以LoadSettings - > CheckForUpdates - > ...)。
但是我得到这种行为:
LoadSettings - > CheckForUpdates - >清理 - >退出 - >清理 - > ...
此外,第一个Cleanup以Task id 1作为参数调用(这是之前执行的任务,对吗?),此Task的状态为Canceled(我从不在任何地方取消任务)。
有谁知道这里出了什么问题?
编辑:好的,根据msdn,如果没有达到延续的条件,它的任务就会被取消。因此,ErrorHandler被取消了,但是如何停止整个链(或通过清理通知其他连续并退出它已被取消)?
答案 0 :(得分:0)
使用Task.WhenAny
,您可以创建在成功处理程序或错误处理程序完成时运行的任务。关闭该任务后,您继续Cleanup
。
设置正确的连续链有时很棘手,但你可以使用像Task.WhenAny
这样的组合函数构建非常复杂的流程图。
如果你可以使用async / await这个任务简化了很多。然后,您可以使用常规控制流构造。您还可以使用迭代器模拟等待。
答案 1 :(得分:0)
设置ErrorHandler - >清理继续,因为OnlyOnRanToCompletion或NotOnCanceled可以工作。此外,也许你可以用异步简化一些事情。这样的事情可以奏效:
try {
var settings = await LoadSettings();
var updatesNeeded = await CheckForUpdates(settings);
await Update(updatesNeeded);
} catch (Exception e) {
ErrorHandler(e);
} finally {
Cleanup();
}
请注意,错误处理和清理在这里是同步的,因为您无法在catch / finally块中等待。您可以通过仅将异常存储在变量中来解决这个问题,稍后您将检查该变量并将其传递给异步错误处理程序。