1

私のアプリケーションでは、実行するアクションの数が設定されています。アクションを実行するスレッドの特定の量を指定したいと思います。一部のアクションは他のアクションよりも時間がかかり、応答を待つ可能性があるため、スレッドが終了したら、キューに戻って次のアクションを開始します。したがって、10個のスレッドの1つが解放されると、新しいアクションが取得され、キューが空になるまで続きます。続行する前に、すべてのアクションが完了するのを待つ必要があります。

そこで、「ああ、このアプリケーションでは.Net 2.0に制限されている」ということを思い出す前に、うまく機能していたTPLを使用して調査とテストを行いました。.Net 2.0のみを使用して再構築しようとしましたが、うまくいきません。私はスレッディングの経験がほとんどありません。

このロジックを.Net2.0に変換するのを手伝ってくれる人はいますか?

List<int> results = new List<int>();
var stopwatch = Stopwatch.StartNew();

Random random = new Random();
using (BlockingCollection<Action> queue = new BlockingCollection<Action>())
{
    for (int i = 0; i < 20; i++)
    {
        int index = i;
        queue.Add(delegate
                      {

                          int foo = random.Next(1, 1500);
                          Thread.Sleep(foo);
                          results.Add(foo);
                          Debug.WriteLine(index + " Working: " + foo + " " + Task.CurrentId);
                      });
    }
    queue.CompleteAdding();

    const int numWorkers = 10;
    Task[] tasks = new Task[numWorkers];
    for (int i = 0; i < numWorkers; i++)
    {
        tasks[i] = Task.Factory.StartNew(() =>
                                             {
                                                 foreach (Action action in queue.GetConsumingEnumerable())
                                                 {
                                                     action();
                                                 }
                                             }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
    }
    Task.WaitAll(tasks);
}
Debug.WriteLine("WaitAll took {0} seconds", stopwatch.Elapsed.TotalSeconds);
4

1 に答える 1

2

少し前にこれをどのように行ったかの概要を説明します。

  1. N個のスレッドを作成する
  2. 作業項目を既知のサイズのリストに入れます
  3. 共有変数を持っているint lastIndex = -1;
  4. すべてのスレッドにこれを実行させます。

    while(true) {
        var index = Interlocked.Increment(ref lastIndex);
        if (index >= list.Count) return;
        ProcessItem(list[index]);
    }
    

とてもシンプルです。

これらすべてをヘルパーメソッドに抽象化します。ハードコーディングする必要がないように、デリゲートが必要ですProcessItem

このヘルパーは、スレッドプールが提供しない正確な並列度を保証する必要がある場合に、.NET4.5でも実際に役立ちます。

于 2013-01-11T22:15:03.467 に答える