You have to set the TaskScheduler.FromCurrentSynchronizationContext on ContinueWith or else it will not be run in the UI context. Here is the MSDN on the override that you must use for this call to ContinueWith.
It should end up looking like this:
.ContinueWith(UpdateLabel, null,
TaskContinuationOptions.OnlyOnRanToCompletion,
TaskScheduler.FromCurrentSynchronizationContext());
It may seem like nothing is happening, but the TPL is currently swallowing your cross thread exception. You should probably use the UnobservedTaskException if you are not going to inspect each result or check for its exception. Otherwise, when garbage collection occurs, the exception will happen then...which could create hard to debug errors.
UPDATE
Based on your update about the main Task being setup and started by a Backgroundworker, my main question is why this could not use a Task to start? In fact, if there is not more in the Method
, then this is really just double work and might confuse other developers. You are already started asynchronously, so why not just do your work within the backgroundworker and use an OnComplete method that will UpdateLabel
(as background workers are already context aware).
The main problem is still the same though, so here are some other solutions if you feel you must use the TPL:
- You can
Invoke
back onto the main UI thread within the UpdateLabel method
- You can pass the current context into the backgroundworker and use that instead
- You can
Wait
for your original Task to return and then use the worker's oncomplete event to update the label.
Here is how I would do this (all pseudo code)
Background Worker Method:
Method() called because of Background worker
private void Method()
{
fileProcessor.ProcessEachMachine(mdetail);
}
Wire up background worker's OnRunWorkerCompleted:
if(!e.Cancelled && !e.Error)
UpdateLabel();
Task only method
Call Method() from the main thread and just let the TPL do its work :)
Task.Factory.StartNew(() => fileProcessor.ProcessEachMachine(mdetail))
.ContinueWith((precedingTask)=>{if(!precedingTask.Error)UpdateLabel;},
null, TaskContinuationOptions.OnlyOnRanToCompletion,
TaskScheduler.FromCurrentSynchronizationContext());