Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# TPL BackgroundThread UIThread图形更新_C#_Winforms_User Interface_Task Parallel Library - Fatal编程技术网

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线程空闲之前不会运行……这是个主意。我会检查一下这是明天的事。非常感谢你的帮助和时间。