使用parallel.for将行添加到数据表中

时间:2010-07-13 11:58:11

标签: vb.net race-condition parallel-processing

我有这个子:

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行。

我怀疑这是因为它试图将相同的行添加两次。 我怎样才能做到这一点?或者我可以使用其他方法来做到这一点?

我需要这个数据表,因为我的应用程序正在那里写一些结果,但是存储与parallel.for一起使用的结果的任何其他方法都可以。

2 个答案:

答案 0 :(得分:2)

这是一种新的并行扩展疾病。您可以轻松编写不安全的代码。 DataTable的MSDN说:

  

线程安全

     

此类型对多线程安全   读操作。你必须同步   任何写操作。

您正在多个线程中执行非线程安全操作。您必须使用lockSpinLock(首选)或ReaderWriterLockSlim。

答案 1 :(得分: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线程到主线程。