0

我一直忙于用 TPL 更新我的大脑,因为我打算将它用于我的新应用程序(它使用 .Net Framework 4.0)。但是,我有一些疑问,有人可能会为我澄清。以前,我有一个进度表,在我启动需要显示其进度的线程后,我将从主(GUI)线程启动。它看起来像这样:

sortThread = New Thread(AddressOf _Sorter.Sort())
_ProgressForm = New FrmProgress()
_Sorter.ProgressForm = _ProgressForm
sortThread.Start()
progressForm.ShowDialog()

基本上,它会初始化线程,初始化 FrmProgress 表单对象并将其分配给 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?)

4

1 回答 1

1

正如您所做的那样,调用应该就足够了。如果两个不同的线程尝试并行调用,第一个将首先执行,然后当 UI 线程空闲时执行第二个。UI 线程不能同时为两个调用提供服务——它们自然是按 FIFO 顺序处理的,因此不存在线程安全问题。任意数量的线程都可以在主线程上调用,而无需担心彼此或使用任何额外的锁定机制。

但是请注意,任何线程调用Invoke都将阻塞,直到主线程可以为调用提供服务。例如,如果您有许多线程同时调用繁重的代码,那么您的各个线程将阻塞调用调用,直到它们开始发挥作用,可以这么说。如果您使用BeginInvoke,那么调用线程将继续执行,并且被调用的方法将被放置在 UI 线程的队列中(它将尽快为该队列提供服务)。

于 2013-06-07T18:31:10.257 回答