Метод вызова для многопоточного приложения?

В моем приложении есть ошибка, аналогичная здесь, где этот человек столкнулся с той же проблемой. Мое приложение является многопоточным, и рабочий поток обновляет Waveformgraph в пользовательском интерфейсе. Я считаю, что именно в этом моя проблема и почему, периодически и в некоторых случаях, я получаю большой красный крестик по крайней мере на одном из моих объектов графика сигнала при запуске приложения. Из чтения и исследования мне нужно использовать метод Invoke или BeginInvoke? Может ли кто-нибудь лучше объяснить и предоставить образец кода, который имеет отношение к моему коду? Образцы, которые я нашел до сих пор, все еще не позволяют мне понять, как мне это делать или что мне нужно делать. Спасибо за помощь.

Этот код находится в событии щелчка swScopeOnOff в основном потоке.

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

Этот код находится в 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

person busarider29    schedule 02.03.2016    source источник


Ответы (1)


Правильный, потокобезопасный вызов на самом деле не так сложен, как можно было бы подумать (даже для поточно-безопасных событий, но это не имеет отношения к этому вопросу).

Я бы порекомендовал вам использовать обычный метод Invoke, например Me.Invoke() (где Me - текущая форма, в противном случае используйте Form1 или как там он называется). Использование BeginInvoke() может быть асинхронным, но оно увеличивает использование памяти и может вызвать утечки памяти, если EndInvoke() не вызывается правильно.

Если вы нацеливаетесь на .NET 4.0 или выше, вы можете просто сделать так:

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

Однако, если вы нацеливаетесь на .NET 3.5 или ниже, потребуется еще несколько строк кода.

'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))
person Visual Vincent    schedule 03.03.2016
comment
Я нацелен на .NET 4.0, так что это упростило. Большое спасибо за код и объяснение каждого из них. - person busarider29; 08.03.2016
comment
@ busarider29: Пожалуйста. На мой взгляд, .NET 4.0 - одно из лучших обновлений. ‹3 - person Visual Vincent; 08.03.2016