【问题标题】: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

我的问题:这似乎可行,但我发现它很慢,甚至我也不太信任它,有没有更有效的方法来实现它?我已经搜索了示例,但我没有找到任何线程在不同的类中执行代码的东西。

非常感谢!

【问题讨论】:

    标签: .net vb.net multithreading winforms thread-safety


    【解决方案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 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-18
      • 1970-01-01
      相关资源
      最近更新 更多