Invoke method for multi thread application?

2019-03-06 07:59发布

问题:

I have a bug in my application which is the same as here which this person was running into the same problem. My application is multi threaded where the worker thread is updating the Waveformgraph on the UI. I believe that is where my problem is and why, periodically, and on occassion I get a big red X in at least one of my waveformgraph objects when running the application. From reading and research, I need to use an Invoke or BeginInvoke method? Can someone please explain better and provide a sample code that is relevant to my code? The samples that I've found so far still have me hazy on how I need to do this or what I need to do. Thank you for your help.

This code is on the swScopeOnOff click event, main thread.

  thread2 = New System.Threading.Thread(AddressOf dataAcquiring)
  thread2.Start()

This code is in dataAcquiring Sub

  Public Sub dataAcquiring()
    'While Scope switch is on, stream each Ai channel's data continuously to its respective WaveForm graph
    Do While swScopeOnOff.Value = True
            data = reader.ReadWaveform(readRate)
            i = 0
            For Each WaveformGraph In WFGS
                WaveformGraph.PlotWaveformAppend(data(i)) 'This line is updating the UI's waveform graphs
                i += 1
            Next
            i = 0
    Loop
End Sub

回答1:

Proper, thread-safe invocation is actually not as hard as one might think (not even for thread-safe events, but that's irrelevant for this question).

I would recommend you to use the normal Invoke method, such as Me.Invoke() (where Me is the current form, if not, use Form1 or whatever it's called instead). Using BeginInvoke() may be asynchronous but it stacks memory usage and can cause memory leaks if EndInvoke() is not called correctly.

If you target .NET 4.0 or higher you can simply do like this:

Me.Invoke(Sub() WaveformGraph.PlotWaveformAppend(data(i)))

However if you target .NET 3.5 or lower it requires a few more lines of code.

'Outside your Sub.
Delegate Sub WaveformAppendDelegate(ByRef WaveformGraph, ByRef data)

'Create a new sub.
Public Sub AppendData(ByRef WaveformGraph, ByRef data)
    WaveformGraph.PlotWaveformAppend(data)
End Sub

'Inside your sub, when you're going to invoke.
Me.Invoke(New WaveformAppendDelegate(AddressOf AppendData), WaveformGraph, data(i))