I am working in C# on .NET 4.0 and have started replacing a number of nested BackgroundWorker setups with Task<T>.
The "nesting" is of this form:
var secondWorker = new BackgroundWorker();
secondWorker.DoWork += (sender, args) =>
{
MoreThings();
};
var firstWorker = new BackgroundWorker();
firstWorker.DoWork += (sender, args) =>
{
args.Result = this.Things();
};
firstWorker.RunWorkerCompleted += (sender, args) =>
{
var result = (bool)args.Result;
// possibly do things on UI
if (result) { secondWorker.RunWorkerAsync(); }
};
secondWorker here plays the role of a callback for firstWorker. The equivalent when using Task<T>, as I understand it, are continuations with ContinueWith(); however, that doesn't allow me to decide whether to actually run the continuation from the control flow in a particular case.
A - from my understanding very unclean - workaround would be this:
var source = new CancellationTokenSource();
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() => { return this.Things(); })
.ContinueWith(t =>
{
// do things on UI
if (!t.Result) { source.Cancel(); }
}, CancellationToken.None, TaskContinuationOptions.NotOnFaulted, uiScheduler)
.ContinueWith(t => { this.MoreThings(); }, source.Token);
This kind of works, but from all the examples I've seen, in this form (accessing the CancellationTokenSource from within the continuation chain - although the task that does is not using the token) it rather looks like abuse of the CancellationToken mechanism. How bad is this really? What would be the proper, "idiomatic" way to cancel the continuation chain based on information determined inside its flow?
(This code on the outside has the intended effect, but I assume it is the wrong way to solve the task with respect to using the existing tools. I am not looking for critique of my "solution" but for the proper way to do it. That's why I am putting this on SO rather than Code Review.)
source.Cancel()wouldn't actually do anything, as your not cooperatively checking if a cancelation was requested in your secondContinueWith. Is that what you want done? - Yuval ItzchakovContinueWith()call which then doesn't run the continuation because of the cancellation. - TeaDrivenDev