同步线程在不同类中执行代码的有效方法?
Posted
技术标签:
【中文标题】同步线程在不同类中执行代码的有效方法?【英文标题】:Efficient way to synchronize threads executing code in different classes? 【发布时间】:2018-09-24 20:14:12 【问题描述】:我只是想知道是否可以以这种“实验性”的方式管理 Windows 窗体进度条:
我想在主窗体中控制栏,因为我有一个线程执行 WorkerClass 对象中的代码,该对象包含一个函数 doWork 来执行繁重的计算。 WorkerClass 包含两个成员变量,它们由 doWork 函数更新,可从表单访问以同步线程并继续跟踪已完成的工作。 由于我需要为这些成员变量提供线程安全,我在主窗体中构建了两个 synclocking 对象并将它们传递给 doWork 函数doWork 函数返回一个主窗体完成工作所需的值,所以我发现我必须告诉窗体线程等待返回值的事实很棘手。
这是 WorkerClass 代码:
Public Class WorkerClass
Private mBarValue As Integer
Private mStartNow As Boolean
Public ReadOnly Property BarValue
Get
Return mBarValue
End Get
End Property
Public ReadOnly Property StartNow As Boolean
Get
Return mStartNow
End Get
End Property
Public Sub New()
mBarValue = 0
mStartNow = False
End Sub
Public Function doWork(ByRef list As ArrayList) As Integer
SyncLock (list.Item(0))
mStartNow = True
End SyncLock
'Do your work and update status
For i As Integer = 0 To 99
Thread.Sleep(10)
SyncLock (list.Item(1))
mBarValue += 1
End SyncLock
Next
SyncLock (list.Item(0))
mStartNow = False
End SyncLock
Return 1000
End Function
End Class
这是主要的表单代码:
Public Class Form1
Private lock As Object
Private lock2 As Object
Private integerNeeded As Integer
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.lock = New Object()
Me.lock2 = New Object()
Dim wc As New WorkerClass()
Dim wT As New Thread(AddressOf workerThread)
Me.ProgressBar1.Value = 0
Me.ProgressBar1.Show()
wT.Start(wc)
Dim canStart As Boolean = False
While Not canStart
SyncLock (lock)
canStart = wc.StartNow
End SyncLock
End While
Debug.WriteLine("Start")
'Bar updater
Dim currentProgress As Integer = 0
While canStart
SyncLock (lock2)
currentProgress = wc.BarValue
End SyncLock
If currentProgress Mod Me.ProgressBar1.Step = 0 Then
Me.ProgressBar1.PerformStep()
Debug.WriteLine(Me.ProgressBar1.Value)
End If
SyncLock (lock)
canStart = wc.StartNow
End SyncLock
End While
While wT.IsAlive 'Wait until the thread is done. Need to guarantee the value is returned
End While
Debug.WriteLine("End")
Me.ProgressBar1.Hide()
REM Rest of the code with integerNeeded here...
End Sub
Private Sub workerThread(wc As Object)
Dim locks As New ArrayList()
locks.Add(lock)
locks.Add(lock2)
integerNeeded = wc.doWork(locks)
End Sub
End Class
我的问题:这似乎可行,但我发现它很慢,甚至我也不太信任它,有没有更有效的方法来实现它?我已经搜索了示例,但我没有找到任何线程在不同的类中执行代码的东西。
非常感谢!
【问题讨论】:
【参考方案1】:您应该使用 .net 提供的内置方法进行同步,例如 AutoResetEvent 和 ManualResetEvent。例如
ManualResetEvent 在内存中维护一个布尔变量。当布尔变量为假时,它会阻塞所有线程,当布尔变量为真时,它会解除对所有线程的阻塞。 例如,借助任务并行库在单独的线程中启动不同的任务
Task task = Task.Factory.StartNew(() =>
GetFoo();
);
Task.Factory.StartNew(() =>
ShowFoo();
);
//Have an instance of manual reset event
static ManualResetEvent manualResetEvent = new
ManualResetEvent(false);
//Send first signal to get Foo then reset it to wait
manualResetEvent.Set();
manualResetEvent.Reset();
//It will wait until manualResetEvent is Set again
manualResetEvent.Set();
Here is a great article that can help you understand the concepts of synchronization.
http://dotnetpattern.com/threading-manualresetevent
【讨论】:
以上是关于同步线程在不同类中执行代码的有效方法?的主要内容,如果未能解决你的问题,请参考以下文章