2016-07-06 22 views
2

このフォーラムや他のC#マルチスレッドに関する多くの投稿を見直した後、私はまだ混乱しており、手元にある問題を処理するのに問題があります。スレッドを待っているC#マルチスレッドの問題

各整数の機能を実行するnumThreadsのスレッド数をdocumentIdsに作成します。 documentIdsは、Count = 100のList<int>であり、これらの各要素のRestitchWorker.RestitchをdocumentIdsに呼び出したいとします。

私は現在下にありますが、5つのスレッドを100個のdocumentIdsのリストに入れてサイクリングする方法を混乱させています。

for (int i = 0; i < documentIds.Count; i++) 
{ 
    if (threadCount < numThreads) 
    { 
     var Worker = new RestitchWorker(documentIds.ElementAt(i)); 
     Thread t_restitchWorker = new Thread(() => Worker.Restitch()); 
     threadCount++; 
     t_restitchWorker.Start(); 
     t_restitchWorker.Join(); 
    } 
} 
+0

。ジョイン?どのような投稿を読んでいたのですか? (あなたの研究の結果へのリンクを追加すると、あなたが何を助けてくれるかを理解するのに役立ちます) –

+3

'Parallel.ForEach(documentIds、new ParallelOptions {MaxDegreeOfParallelism = 5}、processDocumentId);のようなものを考えましたか? – stuartd

答えて

5

この問題は、スレッドではないタスクには本当に適しています。スレッドを明示的に作成するという問題がない場合は、スレッド管理は高価になる可能性があるため、スレッドプールはより効率的になります。

タスクは、100個の長いジョブを100個の明示的なスレッドを作成するのではなくスレッドをプールし、複数のタスクの待機をサポートする使いやすいAPIを持つため、緩やかに並列処理を行う必要がある問題に適しています。タスクの

一覧

あなたは、タスクのリストを作成し、System.Threading.Tasks.Task.WaitAllを呼び出すことによってこれを行うことができます。

var tasks = new List<Task>(); 

for (int i = 0; i < n; ++i) 
{ 
    tasks.Add(Task.Run(action: SomeLongTask)); 
} 

Task.WaitAll(tasks); 

Parallel.Forしかし

これを行うには良い方法それはforループの中にあり、整数を渡す必要があるからです。System.Threading.Tasks.Parallel.For

Parallel.For(0, n, (i) => 
{ 
    SomeLongTask(i); 
}); 
2

アプリケーションをマルチスレッドするメカニズムはたくさんあります。非同期タスク、タスク並列ライブラリ(TPL)、スレッドプール、セマフォーなどを使用することができます。私が一度に生成するスレッドの数を高度に制御する必要がある場合、私が使用したメカニズムは、SemaphoreSlimを使用することです最大スレッド数を設定してから、Waitを使用して、新しいスレッドが使用可能になるのを待ちます。スレッドの安全性について心配することなく、スレッドが作業を実行するために必要な情報を安全にキューに入れてデキューできるように、データ(例:ドキュメントIDのリスト)をConcurrentQueueに入れます。非同期タスクを使用して、実際に作業を開始することができます。

static class Program 
{ 
    private const int _maxWorkers = 10; 
    private static readonly SemaphoreSlim _threadManager = new SemaphoreSlim(_maxWorkers); 

    private void DoStuff() 
    { 
     var queue = new ConcurrentQueue<int>(SomeClass.GetDocumentIds()); 
     var operations = new List<Task>(); 

     while (!queue.IsEmpty) 
     { 
      int documentId; 

      if (queue.TryDequeue(out documentId)) 
      { 
       _threadManager.Wait(); // this will block after max number of threads is met 
       try 
       { 
        operations.Add(GetDocument(documentId); 
       } 
       catch (Exception) 
       { 
        // ignored 
       } 
      } 
     } 

     Task.WaitAll(operations.ToArray()); // finally, this waits till the last remaining tasks are complete 
    } 

    private static async Task GetDocument(int documentId) 
    { 
     await Task.Yield(); 

      try 
      { 
       GoGetDocument(documentId); 
      } 
      catch (Exception) 
      { 
       // ignored 
      } 
      finally 
      { 
       _threadManager.Release(); // release the semaphore when the task completes 
      } 

    } 
+0

DoStuffがここでどのようにどこで呼び出されているのかわかりません。 – GregH

+0

また、DoGetDocumentがどこから来ているのか、それとも何をすべきかわからない...あなたの例から抜けたコードがある? – GregH

+0

また、GetDocument()メソッドは、メソッドのシグネチャを見てタスクを返しますが、メソッド内には何も返されません。 – GregH

関連する問題