(2020.02.25 追記あり)
通常は BackgroundWorker からダイアログのコントロールを操作することはできない。だが、Delegate を経由すれば、可能になる。
Public Class Form1 '*** UIスレッドで実行される関数 *** Private Sub AddRow(color1 As Color, objs As Object()) Dim row1 As New DataGridViewRow row1.CreateCells(Me.DataGrid_Sheet) For i As Integer = LBound(objs) To UBound(objs) row1.Cells(i).Value = objs(i) Next row1.DefaultCellStyle.BackColor = color1 row1.Resizable = DataGridViewTriState.False Me.DataGrid_Sheet.Rows.Add(row1) End Sub '*** UIスレッドへ、更新データを送る Delegate の宣言 Delegate Sub AddRowDelegate(color1 As Color, objs As Object()) Private AddRowDelegate1 As New AddRowDelegate(AddressOf AddRow) '*** バックグラウンドワーカー Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork ' : 中略 Me.Invoke(AddRowDelegate1, color, New Object() { ' セルデータ, } ) ' : 中略 End Sub
ただし、あまりにも更新のスピードが多いと、U/I スレッドがそれへの応答でいっぱいいっぱいになって応答がなくなってしまい、BackgroundWorker の意味がなくなってしまう。
そのような場合、結局、タイマ割り込みで休み休みやった方が安全のようだ。(このあたりは推測にすぎないが…)
(2020.02.25 追記)
本記事では、当初、次のように書いていた。
Me.AddRowDelegate1.Invoke( color, New Object() { ' セルデータ, } )
だが、Windowsフォームで別スレッドからコントロールを操作するには?:.NET TIPS - @ITによると、コントロールのメソッドとして呼ばないと、意味がないようだ(そりゃそうだ)
Me.Invoke( AddRowDelegate1, color, New Object() { ' セルデータ, } )
また、Invoke はメインスレッドをブロックするが、BeginInvoke だと待機状態になったタイミングで実行するとあるので、BeginInvokeを使えば U/I スレッドがいっぱいいっぱいになることは避けられるかもしれない