多线程工作者线程状态

时间:2010-08-27 12:14:54

标签: c# .net multithreading threadpool thread-state

我将我的主题创建为

 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事件

6 个答案:

答案 0 :(得分:1)

确定所有线程何时完成很简单。

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

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

你能详细说明你的其他要求吗?

答案 1 :(得分:1)

您可以查看主题的ThreadState属性。

最好使用异步方法。这会为您提供一个WaitHandle对象,您可以使用WaitHandle.WaitAll等待所有异步方法完成。

以下是异步编程的介绍: http://msdn.microsoft.com/en-us/library/aa719598%28v=VS.71%29.aspx

答案 2 :(得分:1)

首先,我必须指出创建100,150,255等线程可能不是一个好主意。您可能最好使用ThreadPoolTask类(如果使用.NET 4.0)。除此之外,有两种完善的方法可以等待所有线程完成。

加入主题。

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's website处获得非常简单的实现。

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();

答案 3 :(得分:1)

您肯定希望将Task类用于此Parallel.ForEach或更高级别的概念,例如Thread。直接使用Task类非常痛苦。

我最近wrote a blog post比较了各种异步方法,按照从最佳(Thread)到最差(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); 的示例,演示了您想要做的事情:

{{1}}

答案 4 :(得分:1)

向Searcher添加一个委托,并从主线程传递一个回调方法,每个线程在完成后将调用该方法。在启动每个线程时,将其添加到由线程的ManagedThreadId键入的Dictionary中。当每个线程完成时,回调将从Dictionary中删除线程并检查计数是否为零。

        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);
            }
        }

如果您有多个线程比一次运行要多,请将它们放入队列并在旧线程完成时剥离它们(使用回调)。

答案 5 :(得分:0)

为什么不能使用临界区受保护的单个变量来控制多个活动线程?线程函数可以修改此变量(当然已进入临界区)。