为数百万个线程

时间:2016-11-14 16:38:42

标签: vb.net multithreading threadpool queueuserworkitem

我需要处理数百万个文件。目前,我使用自定义线程管理器通过使用DataGridView来跟踪线程和计时器来检查是否可以启动更多线程来完成工作。有点像(sudo):

Private Sub ThreadManager()
    If AVailableThreads > 0 then
        Dim t as Threading.Thread = New Thread(AddressOf MyThread)
        t.Start()
        AvailableThreads = AvailableThreads - 1
        ThreadManager()
    End If
End Sub

这有许多缺点,主要是CPU和内存使用率很高,因为上述每个线程都会独立处理完整目录而不是每个文件。

所以我改写了这个过程。现在我有一个类将在文件级执行该过程并将结果报告给主线程;像这样:

Imports System.IO

Public Class ImportFile

    Public Class ImportFile_state
        Public ID as Long = Nothing
        Public FilePath as String = Nothing
        Public Result as Boolean = False
    End Class

    Public Event ReportState(ByVal state as ImportFile_state)

    Dim _state as ImportFile_state = New ImportFile_State

    Public Sub New(ByVal ID as Long, ByVal FilePath as String)
        MyBase.New()
        _state.ID = ID
        _state.FilePath = FilePath
    End Sub

    Public Sub GetInfo()
        'Do the work here, but just return the result for this demonstration
        Try
            _state.Result = True
        Catch ex As Exception
            _state.Result = False
        Finally
            RaiseEvent ReportState(_state)
        End Try
    End Sub
End Class

上面的类就像魅力一样,非常快,几乎没有内存,几乎没有CPU。虽然我只能用几百个线程使用Threading.Thread进程测试它。

现在我想使用ThreadPool.QueueUserWorkItem为每个文件执行上面的类,允许系统控制在任何给定时间运行的线程数。但是,我知道我不能在没有锁定服务器的情况下将数百万个线程转储到ThreadPool中。我已经对此做了大量研究,我只能找到关于在一些线程中使用ThreadPool.QueueUserWorkItem的示例/讨论。我需要的是解雇数百万这些线程。

所以,我有两个问题:1)我是否应该尝试使用ThreadPool.QueueUserWorkItem来运行这么多线程,2)下面的代码是否足以执行此过程而不会锁定我的服务器?

到目前为止,这是我的代码:

        For Each subdir As String In Directory.GetDirectories(DirPath)
            For Each fl In Directory.GetFiles(subdir)
                'MsgBox(fl)
                Dim f As ImportFile = New ImportFile(0, fl)
                AddHandler f.ReportState, AddressOf GetResult
                ThreadPool.QueueUserWorkItem(New Threading.WaitCallback(AddressOf f.GetInfo))
                ThreadPool.GetAvailableThreads(worker, io)
                Do While (worker) <= 0
                    Thread.Sleep(5000)
                    ThreadPool.GetAvailableThreads(worker, io)
                Loop
            Next
        Next

0 个答案:

没有答案