0

ワーカーをキューに追加したいのですが、最初の N 個のワーカーのみを並列処理します。私が見つけたすべてのサンプルは C# にあります。

これはおそらくプログラマーにとっては簡単なことですが、私はそうではありません。VB については、簡単なプログラムを作成するのに十分な知識があります。

しかし、私の最初のアプリケーションは、突然 100% の CPU に達してクラッシュするまでは正常に動作します。助けてください (はい、これを投稿する前に検索に 5 時間も費やしました...)

詳細コンテキスト: 100 万を超えるディレクトリ/サブディレクトリを持つファイル サーバー全体で、ディレクトリ構造、ファイル、およびアクセス許可の再帰的なインベントリを実行します。

プロセスは順次実行されますが、完了するまでに数か月かかります。経営陣はすでに私の首を呼吸しています。タスクを使用しようとすると、スレッド数が約 1000 になり、CPU 使用率が 100% になり、応答が停止してクラッシュします。これは、112 GB RAM を搭載した 16 コア サーバー上にあります。

-- 追加 セマフォの使用に関するサンプルが提供されているので、これを入れました。

Public Class InvDir
    Private mSm as Semaphore
    Public Sub New(ByVal maxPrc As Integer)
        mSm = New Semaphore(maxPrc, maxPrc)
    End Sub

    Public Sub GetInventory(ByVal Path As String, ByRef Totals As Object, ByRef MyData As Object)
        mSm.WaitOne()

        Task.Factory.StartNew(Sub()
                Dim CurDir As New IO.DirectoryInfo(Path)
                Totals.SubDirectoryCount += CurDir.GetDirectories().Count
                Totals.FilesCount += CurDir.GetFiles().Count
                For Each CurFile As IO.FileInfo in CurDir.EnumerateFiles()
                    MyData.AddFile(CurFile.FileName, CurFile.Extension, CurFile.FullName, CurFile.Length)
                Next
                End Sub).ContinueWith(Function(x) mSm.Release())
    End Sub
End Class
4

1 に答える 1

1

ディスク I/O でマルチスレッド化を試みています。より多くのスレッドを投げているため、速度が低下している可能性があります。スレッドがいくつあっても、ディスクは物理的に一度に 1 つの位置しかシークできません。(実際、シリアルで動作するとおっしゃいました。)

同時スレッド数を制限したい場合は、Semaphore. セマフォは、一度にコードを実行できるスレッド数を指定できることを除いて、syncLock に似ています。次の例では、セマフォによって 3 つのスレッドの実行が許可されています。それ以上は、いずれかが終了するまで待つ必要があります。MSDN ページからいくつかの変更されたコード:

Public Class Example

    ' A semaphore that simulates a limited resource pool.
    '
    Private Shared _pool As Semaphore

    <MTAThread> _
    Public Shared Sub Main()
        ' Create a semaphore that can satisfy up to three
        ' concurrent requests. Use an initial count of zero,
        ' so that the entire semaphore count is initially
        ' owned by the main program thread.
        '
        _pool = New Semaphore(0, 3)          

    End Sub

    Private Sub SomeWorkerMethod()
        'This is the method that would be called using a Task.
        _pool.WaitOne()
        Try
            'Do whatever
        Finally
            _pool.Release()
        End Try
    End Sub
End Class

すべての新しいスレッドは を呼び出す必要があります_pool.WaitOne()。これは、実行中のスレッドが 3 つ未満になるまで順番を待つように指示します。セマフォが通過を許可するまで、すべてのスレッドがブロックされます。

すべてのスレッドは_pool.Release()、次の待機中のスレッドの開始を許可できることをセマフォに知らせるためにも呼び出す必要があります。たとえ例外があっても、それは重要です。スレッドが呼び出されない場合Release()、セマフォはスレッドを永久にブロックします。

本当に 5 か月かかる場合は、ドライブのクローンを作成し、同じドライブの複数のインスタンスでチェックを実行して、それぞれが異なるセクションを確認するのはどうでしょうか?

于 2016-05-07T02:36:40.210 に答える