All, I have a Task that runs on a background thread and does some heavy lifting. The way I have it set up is that whilst this is being done, the UI thread updates the GUI with progress information, some of which use animated .gif files. Take a look at the following example code to illustrate the problem
TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task<bool> task = Task.Factory.StartNew(() =>
{
// Heavy work.
if (heavyWorkCompleted)
MethodToUpdateGui(uiScheduler); // Update DataGridView ImageCell on UI thread
// More work.
}
I have a “In Progress” image that is shown in the appropriate DGV image cell during execution of “Heavy Work”, if “Heavy Work” is successful this image changes to a tick (in DGV1), then MethodToUpdateGui(uiScheduler) uses this (just changed) image in DGV1 to update DGV2. However, when the MethodToUpdateGui(uiScheduler) runs it sometimes updates the DataGridView (DGV2) too fast. What I mean by this, is that the image is not the tick I want (and it should be due to successfull compleation) it is the “In Progress” image. It seems that the DGV is not updating fast enough for what I am doing.
Is there a better way to do this? Do I dare to spin the background thread after the GUI update to allow DGV1 to “catch-up” [this is nasty!]?
Thanks for your time.
The issue here is that that TPL uses SynchronizationContext.Post to send the message to the UI thread. When the method runs, the Task will run asynchronously, which will, in turn, not update the GUI immediately.
If you want to make sure that the GUI is updated, the simplest option would be to have your
MethodToUpdateGuiblock by waiting on the Task scheduled viauiScheduler.This would look something like:
This is better than trying to spin, as it will block and get notified by the TPL automatically.
This is effectively doing
Control.Invokeinstead ofControl.BeginInvoke, in Windows Forms terminology.