3

スレッドを次のように作成します

 for (int i = 0; i < threadCount; i++)
 {
     Searcher src = new Searcher(i, this);

     threads[i] = new Thread(new ThreadStart(src.getIpRange));
     threads[i].Name = string.Format(i.ToString());
  }

  foreach (Thread t in threads)
  {
     t.Start();
  }

threadCount(= 100、150、255など)を使用しますが、動作しているスレッドの数を知ることができません。実行時に。

そして、すべてのスレッドがいつジョブを終了するかを制御したいと思います。そして、backgroundWorkerのRunWorkerCompletedイベントのように、「すべてのスレッドが停止し、ジョブが完了しました...」のようなメッセージを表示します。

4

6 に答える 6

1

すべてのスレッドがいつ終了するかを判断するのは簡単です。

for (int i = 0; i < threadCount; i++)
{
    threads[i].Join();
}

Console.WriteLine("All threads are done!");

他の要件について詳しく説明していただけますか?

于 2010-08-27T12:19:41.700 に答える
1

ThreadStateスレッドのプロパティを確認できます。

非同期メソッドを使用する方が良いかもしれません。これによりオブジェクトが得られ、すべての非同期メソッドが終了するまで待つWaitHandleことができます。WaitHandle.WaitAll

非同期プログラミングの概要は次のとおりです: http://msdn.microsoft.com/en-us/library/aa719598%28v=VS.71%29.aspx

于 2010-08-27T12:19:50.077 に答える
1

まず、100、150、255 などのスレッドを作成することは、おそらく良い考えではないことを指摘しなければなりません。ThreadPoolまたはクラスを使用する方がよいTask場合があります (.NET 4.0 を使用している場合)。それとは別に、すべてのスレッドが完了するまで待機するための確立された方法が 2 つあります。

スレッドに参加します。

Thread.Joinターゲットスレッドが終了するまでブロックします。

for (int i = 0; i < threadCount; i++) 
{ 
   Searcher src = new Searcher(i, this); 
   threads[i] = new Thread(new ThreadStart(src.getIpRange)); 
   threads[i].Name = string.Format(i.ToString()); 
} 

foreach (Thread t in threads) 
{ 
   t.Start(); 
} 

foreach (Thread t in threads)
{
   t.Join(); 
}

CountdownEvent を使用します。

CountdownEventは、内部カウントがゼロになるまで待機します。を使用する場合は、この方法が適していますThreadPool。.NET 4.0 を使用していない場合は、Joe Albahari の Web サイトで非常に簡単な実装を入手できます。

var finished = new CountdownEvent(1);

for (int i = 0; i < threadCount; i++) 
{ 
   finished.AddCount();
   Searcher src = new Searcher(i, this); 
   threads[i] = new Thread(
     () =>
     {
        try
        {
          src.getIpRange();
        }
        finally
        {
          finished.Signal();
        }
     }
   threads[i].Name = string.Format(i.ToString()); 
} 

foreach (Thread t in threads) 
{ 
   t.Start(); 
} 

finished.Signal();
finished.WaitOne();
于 2010-08-27T13:10:15.447 に答える
1

デリゲートを Searcher に追加し、各スレッドが終了時に呼び出すメイン スレッドからのコールバック メソッドを渡します。各スレッドを起動するときに、スレッドの ManagedThreadId をキーとするディクショナリにスレッドを追加します。各スレッドが終了すると、コールバックはそのスレッドをディクショナリから削除し、カウントがゼロかどうかを確認します。

        Dictionary<int, Thread> activeThreads = new Dictionary<int, Thread>();            

           for (int i = 0; i < threadCount; i++)
            {
                Searcher src = new Searcher(i, this);
                src.Done = new SearcherDoneDelegate(ThreadDone);
                threads[i] = new Thread(new ThreadStart(src.getIpRange));
                threads[i].Name = string.Format(i.ToString());
            }

            foreach (Thread t in threads)
            {
                lock (activeThreads)
                {
                    activeThreads.Add(t.ManagedThreadId, t);
                }
                t.Start();
            }


        }
        public void ThreadDone(int threadIdArg)
        {
            lock (activeThreads)
            {
                activeThreads.Remove(threadIdArg);
                if (activeThreads.Count == 0)
                {
                    // all done
                }
            }
        }

        public delegate void SearcherDoneDelegate(int threadIdArg);
        public static object locker = new object();



        public class Searcher
        {
            public SearcherDoneDelegate Done { get; set; }
            public void getIpRange()
            {
                Done(Thread.CurrentThread.ManagedThreadId);
            }
        }

一度に実行したいスレッドよりも多くのスレッドがある場合は、それらを Queue に入れ、古いスレッドが終了したときにそれらを剥がします (コールバックを使用します)。

于 2010-08-27T16:46:16.940 に答える
1

Taskこのクラスまたは のような高レベルの概念にクラスを使用することは間違いありませんParallel.ForEach。クラスを直接使用するのThreadは非常に面倒です。

私は最近、さまざまな非同期アプローチを比較したブログ記事を書きましTaskThread

を使用した例を次にTask示します。これは、やりたいことを示しています。

// Start all tasks
var threads = new Task[threadCount];
for (int i = 0; i < threadCount; i++) 
{ 
  Searcher src = new Searcher(i, this); 
  threads[i] = Task.Factory.StartNew(src.getIpRange);
}

// How many are running right now?
var runningCount = threads.Count(x => x.Status == TaskStatus.Running);

// Register a callback when they have all completed (this does not block)
Task.Factory.ContinueWhenAll(threads, MyCallback);
于 2010-08-27T13:24:16.737 に答える
0

アクティブなスレッドの数を制御するために、クリティカル セクションで保護された単一の変数を使用できないのはなぜですか? スレッド関数はこの変数を変更できます (もちろん、クリティカル セクションに入っています)。

于 2010-08-27T12:17:48.113 に答える