为什么ThreadPool.GetAvailableThreads不工作?

时间:2010-02-05 09:15:38

标签: multithreading

我有一个方法来处理来自使用多个线程的数据表中的行,它将所有工作项排队,然后检查它们是否已经全部处理过,而不是离开方法,直到它们有。

它似乎在开发中运行良好,但是当我进入服务器(64位)进行测试时,它不会在方法结束时等待。它似乎甚至没有进行Thread.Sleep()调用,因为该方法会立即退出。

离开方法后它将继续处理数据行,但这不是我想要的。

有什么想法吗? 感谢

Public Sub ProcessAll(ByVal collection As DataTable, ByVal processDelegate As WaitCallback)
        Dim workItem As DataRow
        Dim availableThreads As Integer
        Dim completionPortThreads As Integer


        ThreadPool.SetMaxThreads(MAX_THREADS, MAX_THREADS)

        ' loop round processing each pending record adding them to the Thread Queue
        For Each workItem In collection.Rows
            ThreadPool.QueueUserWorkItem(processDelegate, workItem)
        Next

        ' The ThreadPool is a collection of background threads, thus we need to do something to stop the main thread from moving on
        Do
            Thread.Sleep(1000)
            ThreadPool.GetAvailableThreads(availableThreads, completionPortThreads)
            ' in the case that all threads are free (how we check all are complete) wait a few seconds just to make sure
            If availableThreads = MAX_THREADS Then
                Thread.Sleep(5000)
                ThreadPool.GetAvailableThreads(availableThreads, completionPortThreads)
            End If
        Loop While availableThreads < MAX_THREADS
End Sub

1 个答案:

答案 0 :(得分:5)

你不应该这样做,等到所有的行都完成了。

你应该使用一种通知方法,从你的处理代码中,告诉一段代码“嘿,我刚刚完成一行”。

这样,您可以更轻松地跟踪已处理的行数。

我会这样做:

  1. 添加一个Int32值,初始化为0,用于跟踪已处理的数量
  2. 使用Interlocked.Increment在您的代理中增加此项
  3. 在增加计数器
  4. 后,在您的代理中设置一个事件对象
  5. 在您的main方法中,我会等待事件设置,然后检查计数器。如果不够高,请回路并再次等待。
  6. 即。类似的东西:

    private volatile Int32 _Processed = 0;
    private AutoResetEvent _RowProcessedEvent = new AutoResetEvent(false);
    
    ... in your delegate:
    Interlocked.Increment(ref _Processed);
    _RowProcessedEvent.Set();
    
    ... in your main method:
    while (_Processed < collection.Rows.Count)
    {
        _RowProcessedEvent.WaitOne(Timeout.Infinite);
    }
    

    不要忘记在完成后关闭事件对象。