所有,我有一个Task
在后台线程上运行,并做了一些繁重的工作。我设置它的方式是,在完成此操作时,UI线程使用进度信息更新GUI,其中一些使用动画.gif文件。请查看以下示例代码来说明问题
TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task<bool> task = Task.Factory.StartNew(() =>
{
// Heavy work.
if (heavyWorkCompleted)
MethodToUpdateGui(uiScheduler); // Update DataGridView ImageCell on UI thread
// More work.
}
我有一个&#34;进展中&#34;在执行&#34;重工作&#34;期间显示在适当的DGV图像单元格中的图像,如果&#34;重工作&#34;成功此图像更改为刻度(在DGV1中),然后MethodToUpdateGui(uiScheduler)
使用DGV1中的此(刚更改的)图像更新DGV2。但是,当MethodToUpdateGui(uiScheduler)
运行时,它有时会更快地更新DataGridView(DGV2)。我的意思是,图像不是我想要的刻度(它应该是由于成功完成)它是&#34;进行中&#34;图片。似乎DGV没有足够快地更新我正在做的事情。
有更好的方法吗?在GUI更新之后我是否敢于旋转后台线程以允许DGV1进入&#34;赶上&#34; [这很讨厌!]?
感谢您的时间。
答案 0 :(得分:1)
有更好的方法吗?在GUI更新后我是否敢于旋转后台线程以允许DGV1“赶上”[这很讨厌!]?
这里的问题是TPL使用SynchronizationContext.Post将消息发送到UI线程。当该方法运行时,Task将异步运行,而不会立即更新GUI。
如果您想确保更新GUI,最简单的选择是等待通过MethodToUpdateGui
安排的任务来阻止uiScheduler
。
这看起来像是:
void MethodToUpdateGui(TaskScheduler uiScheduler)
{
var updateTask = Task.Factory.StartNew( () =>
{
// update gui
}, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
// Block until Task completes...
updateTask.Wait();
}
这比尝试旋转更好,因为它会阻止并自动通知TPL。
在Windows窗体术语中,这实际上是Control.Invoke
而不是Control.BeginInvoke
。