我将我的主题创建为
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事件
答案 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等线程可能不是一个好主意。您可能最好使用ThreadPool
或Task
类(如果使用.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)
为什么不能使用临界区受保护的单个变量来控制多个活动线程?线程函数可以修改此变量(当然已进入临界区)。