1

私はこのサブを持っています:

Private Sub error_out(ByVal line As Integer, ByVal err_col As Integer, ByVal err_msg As String)

            Dim ln = t_erori.Rows.Add
            ln.Item(0) = line
            ln.Item(err_col) = err_msg
            ln.Item(3) = err_col
    End Sub

これは、parallel.forループで実行されているいくつかの関数によって呼び出されています。

問題は、時々(完全にランダムに)エラーが発生することです:

Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index

ライン上Dim ln = t_erori.Rows.Add

これは、同じ行を2回追加しようとしているためだと思います。どうすればこれを機能させることができますか?または、これを行うために他にどのような方法を使用できますか?

私のアプリはそこにいくつかの結果を書き込んでいるので、このデータテーブルが必要ですが、parallel.forで機能する結果を保存する他の方法は問題ありません。

4

2 に答える 2

2

これは、新しい並列拡張の病気です。安全でないコードを簡単に書くことができます。DataTableのMSDNによると:

スレッドセーフ

このタイプは、マルチスレッド読み取り操作に対して安全です。書き込み操作を同期する必要があります。

複数のスレッドでスレッドセーフでない操作を実行しています。lockまたは、SpinLock(推奨)またはReaderWriterLockSlimのいずれかを使用する必要があります。

于 2010-07-13T12:16:04.547 に答える
1

SyncLockこれを修正するための素朴なアプローチは、すべてをブロックにラップすることです。

Private Sub error_out(ByVal line As Integer, ByVal err_col As Integer, ByVal err_msg As String) 

  SyncLock t_erori
    Dim ln = t_erori.Rows.Add 
    ln.Item(0) = line 
    ln.Item(err_col) = err_msg 
    ln.Item(3) = err_col 
  End SyncLock

End Sub 

error_outここでの問題は、すべてのスレッドが同じロックを争う必要があるため、の実行を効果的にシリアル化したことです。その結果、同等の非並列バージョンよりも実行速度が低下する可能性があります。

ここでスレッドを利用する最も簡単な方法は、行をワーカースレッドに追加する操作全体を委任しDataTable、メインスレッドに実行を続行させてから、ワーカースレッドをメインスレッドに結合するThread.Joinことです。メインスレッドが操作の完了を要求する時間です。

于 2010-07-15T03:41:27.397 に答える