使用TaskScheduler控制.Invoke与任务

Tom*_*lla 5 c# multithreading task

我看了一遍,我找不到答案.使用是否更好,更糟或无动于衷:

{
...
RefreshPaintDelegate PaintDelegate = new RefreshPaintDelegate(RefreshPaint);
Control.Invoke(PaintDelegate);
}

protected void RefreshPaint()
{
    this.Refresh();
}
Run Code Online (Sandbox Code Playgroud)

...要么...

Task.Factory.StartNew(() =>
{
    this.Refresh();
},
CancellationToken.None,
TaskCreationOptions.None,
uiScheduler);
Run Code Online (Sandbox Code Playgroud)

cas*_*One 3

假设这uiScheduler是一个将调用委托给 UI 线程的调度程序,我想说,从功能上讲,使用这两者是无关紧要的(例外的是对 Control.Invoke 的调用将阻塞直到调用完成,而对 Control.Invoke 的调用将不会阻塞Task) ,但是,您始终可以使用Control.BeginInvoke使它们在语义上等效)。

从语义的角度来看,我认为 usingControl.Invoke(PaintDelegate)是一种更好的方法;当使用 a 时,Task您正在隐式声明您想要执行一个工作单元,通常,该工作单元具有与其他工作单元一起调度的上下文,调度程序决定如何委派该工作(通常,它是多线程的,但在本例中,它被编组到 UI 线程)。还应该说的是, 和 之间没有明确的联系uiSchedulerControl链接到 UI 线程,调用应该是一个(通常,它们都是相同的,但有可能有多个 UI 线程,尽管非常罕见)。

然而,在使用 时Control.Invoke,您想要做的事情的意图很明确,您想要将调用编组到正在Control泵送消息的 UI 线程,并且此调用完美地表明了这一点。

然而,我认为最好的选择是使用实例SynchronizationContext ;它抽象出这样一个事实:您需要同步对该上下文的调用,这与其他两个选项相反,这两个选项要么对调用的意图不明确 ( Task),要么在执行方式上非常具体 ( Control.Invoke)。