我一直忙于用TPL更新我的大脑,因为我打算将它用于我的新应用程序(使用.Net Framework 4.0)。但是我怀疑有人可能会为我澄清。以前,我有一个进度表单,在我启动需要显示其进度的线程后,我将从主(GUI)线程启动。它看起来像这样:
sortThread = New Thread(AddressOf _Sorter.Sort())
_ProgressForm = New FrmProgress()
_Sorter.ProgressForm = _ProgressForm
sortThread.Start()
progressForm.ShowDialog()
基本上它会初始化线程,初始化一个FrmProgress表单对象并将其分配给Sorter对象,然后Sorter对象将从单独线程上的Sort()子更新进度表(包含进度条和一些标签)。通过检查FrmProgress表单的InvokeRequired属性来更新这些控件属性,如果需要,它将使用要更新的控件的Invoke()方法...例如:
Public Sub IncrementProgressBar(x As Integer)
If Me.InvokeRequired Then
pb_MainProgressBar.Invoke(Sub() IncrementProgressBar(x))
Else
pb_MainProgressBar.Increment(x)
End If
End Sub
现在我有兴趣使用TPL启动可能想要更新进度条的单独工作线程(多个)。我应该使用相同的模式还是应该考虑访问在主GUI线程中获得的公共TaskScheduler.FromCurrentSynchronizationContext上下文?在这两种情况下,我想我应该在表单上提供某种锁定机制(SyncLock?)
答案 0 :(得分:1)
调用就足够了,就像你在做的那样。如果两个不同的线程尝试并行调用,则第一个将首先执行,然后在UI线程空闲时执行第二个。 UI线程无法同时为两个调用提供服务 - 它们自然以FIFO顺序处理,因此线程安全没有问题。任何数量的线程都可以在主线程上调用,而不必担心彼此或使用任何其他锁定机制。
但请注意,任何调用Invoke
的线程都将阻塞,直到主线程可以为该调用提供服务。例如,如果你有许多线程同时调用繁重的代码,那么你的各种线程会阻止调用调用,直到他们得到了他们的反应,可以这么说。如果使用BeginInvoke
,则调用线程将继续执行,并且调用的方法将被放置在UI线程的队列中(它将尽快为其服务)。