C# TPL BackgroundThread UIThread图形更新
总之,我有一个C# TPL BackgroundThread UIThread图形更新,c#,winforms,user-interface,task-parallel-library,C#,Winforms,User Interface,Task Parallel Library,总之,我有一个任务,它在后台线程上运行,并执行一些繁重的工作。我设置它的方式是,在执行此操作时,UI线程使用进度信息更新GUI,其中一些使用动画.gif文件。请看下面的示例代码来说明这个问题 TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); Task<bool> task = Task.Factory.StartNew(() => { // Heavy work
任务
,它在后台线程上运行,并执行一些繁重的工作。我设置它的方式是,在执行此操作时,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.
}
TaskScheduler uiScheduler=TaskScheduler.FromCurrentSynchronizationContext();
Task Task=Task.Factory.StartNew(()=>
{
//繁重的工作。
如果(重型工程已完成)
MethodToUpdateGui(uiScheduler);//在UI线程上更新DataGridView ImageCell
//更多的工作。
}
我有一个“正在进行”的图像,在执行“繁重工作”期间显示在相应的DGV图像单元格中,如果“繁重工作”成功,则此图像将变为勾号(在DGV1中),然后MethodToUpdateGui(uiScheduler)
使用DGV1中的此(刚刚更改)图像更新DGV2。但是,MethodToUpdateGui(uiScheduler)在
运行时,有时会太快地更新DataGridView(DGV2)。我的意思是,图像不是我想要的勾号(这应该是由于成功完成),而是“正在进行”的图像。DGV的更新速度似乎不够快,无法满足我的要求
有更好的方法吗?我敢在GUI更新后旋转后台线程以允许DGV1“追赶”[这很讨厌!]
谢谢你抽出时间
有更好的方法吗?我敢在GUI更新后旋转后台线程以允许DGV1“追赶”[这很讨厌!]
这里的问题是TPL用来将消息发送到UI线程。当方法运行时,任务将异步运行,这反过来不会立即更新GUI
如果您想确保GUI得到更新,最简单的选择是通过等待通过uiScheduler
调度的任务来阻止方法更新GUI
这看起来像:
void MethodToUpdateGui(TaskScheduler uiScheduler)
{
var updateTask = Task.Factory.StartNew( () =>
{
// update gui
}, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
// Block until Task completes...
updateTask.Wait();
}
这比尝试旋转要好,因为它会自动阻止并得到TPL的通知
在Windows窗体术语中,这实际上是在执行控件.Invoke
而不是控件.BeginInvoke
有更好的方法吗?我敢在GUI更新后旋转后台线程以允许DGV1“追赶”[这很讨厌!]
这里的问题是TPL用来将消息发送到UI线程。当方法运行时,任务将异步运行,这反过来不会立即更新GUI
如果您想确保GUI得到更新,最简单的选择是通过等待通过uiScheduler
调度的任务来阻止方法更新GUI
这看起来像:
void MethodToUpdateGui(TaskScheduler uiScheduler)
{
var updateTask = Task.Factory.StartNew( () =>
{
// update gui
}, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
// Block until Task completes...
updateTask.Wait();
}
这比尝试旋转要好,因为它会自动阻止并得到TPL的通知
在Windows窗体术语中,这有效地实现了
控制。调用而不是控制。开始调用。我实际上是这样做的。在所有使用uiScheduler
的GUI更新中,我总是使用uiTask.Wait()
(包装在try/catch
中捕获任何聚合异常,当然是这样),但是“赛车”还在发生!我很困惑…@Killercam你在做“完成”吗"消息以同样的方式处理?完成消息是通过一个延续来处理的。我不等待延续,并且在这个问题出现后,延续委托会被很好地调用。@Killercam这听起来像是有什么东西在阻止UI更新,因为延续在UI线程空闲之前不会运行……这是个主意。我会检查一下这是明天。非常感谢您的帮助和时间。我确实这样做了。在所有使用uiScheduler
的GUI更新中,我总是使用uiTask.Wait()
(包装在try/catch
中以捕获任何aggregateeexception
当然),但这种“竞赛”仍然在发生!?我很困惑…@Killercam你在做什么“完成"消息以同样的方式处理?完成消息是通过一个延续来处理的。我不等待延续,并且在这个问题出现后,延续委托会被很好地调用。@Killercam这听起来像是有什么东西在阻止UI更新,因为延续在UI线程空闲之前不会运行……这是个主意。我会检查一下这是明天的事。非常感谢你的帮助和时间。