Reputation: 183
I built a small chain of tasks with conditional continuations, however I'm experiencing some weired behavior. My chain looks like this:
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
As I understood this chain should run asynchronically (i.e. not in the ui thread) but one after another (so LoadSettings -> CheckForUpdates -> ...).
However I get this behavior:
LoadSettings -> CheckForUpdates -> Cleanup -> Exit -> Cleanup -> ...
Also, the first Cleanup gets called with the Task id 1 as parameter (this is the task executed right before, right?) and this Task had the status Canceled (and I never cancel a Task anywhere).
Does anyone know what's going wrong here?
Edit: Ok, according to msdn if a condition for a continuation is not met its task get canceled. So ErrorHandler gets canceled, but how can I stop the complete chain (or notify the other continuations with cleanup and exit that it has been canceled)?
Upvotes: 1
Views: 90
Reputation: 1838
Setting up the ErrorHandler -> Cleanup continuation as OnlyOnRanToCompletion or NotOnCanceled would work. Also, maybe you could simplify things a bit with async. Something like this could work:
try {
var settings = await LoadSettings();
var updatesNeeded = await CheckForUpdates(settings);
await Update(updatesNeeded);
} catch (Exception e) {
ErrorHandler(e);
} finally {
Cleanup();
}
Note that the error handling and cleanup would be synchronous here, since you can't await in a catch/finally block. You could get around that by only storing the exception in a variable, which you later check for null and pass to the async error handler.
Upvotes: 0
Reputation: 171246
Using Task.WhenAny
you can create a task that runs when either the success handler or the error handler have completed. Off of that task you continue with Cleanup
.
It is sometimes tricky to set up the continuation chains right, but you can construct pretty complicated flow graphs using combinator functions like Task.WhenAny
.
If you can use async/await the task simplifies a lot. You can then use normal control flow constructs. You can also simulate await using iterators.
Upvotes: 0