我有这段代码:
var list = new List<int>();
for(int i=0;i<10;i++) list.Add(i);
for(int i=0;i<10;i++)
{
ThreadPool.QueueUserWorkItem(
new WaitCallback(x => {
Console.WriteLine(x);
}), list[i]);
}
我想知道所有线程池线程何时完成了他们的工作。我该怎么做?
答案 0 :(得分:23)
您需要自己跟踪。
一个选项是使用计数器和重置事件:
int toProcess = 10;
using(ManualResetEvent resetEvent = new ManualResetEvent(false))
{
var list = new List<int>();
for(int i=0;i<10;i++) list.Add(i);
for(int i=0;i<10;i++)
{
ThreadPool.QueueUserWorkItem(
new WaitCallback(x => {
Console.WriteLine(x);
// Safely decrement the counter
if (Interlocked.Decrement(ref toProcess)==0)
resetEvent.Set();
}),list[i]);
}
resetEvent.WaitOne();
}
// When the code reaches here, the 10 threads will be done
Console.WriteLine("Done");
答案 1 :(得分:14)
在.NET Framework 4+中使用方便的System.Threading.CountdownEvent类:
const int threadCount = 10;
var list = new List<int>(threadCount);
for (var i = 0; i < threadCount; i++) list.Add(i);
using (var countdownEvent = new CountdownEvent(threadCount))
{
for (var i = 0; i < threadCount; i++)
ThreadPool.QueueUserWorkItem(
x =>
{
Console.WriteLine(x);
countdownEvent.Signal();
}, list[i]);
countdownEvent.Wait();
}
Console.WriteLine("done");
答案 2 :(得分:9)
我不确定ThreadPool是否公开了这样的功能,但你可以使用等待句柄,顺便说两次迭代似乎是不必要的:
var events = new ManualResetEvent[10];
var list = new List<int>();
for (int i = 0; i < 10; i++)
{
list.Add(i);
events[i] = new ManualResetEvent(false);
int j = i;
ThreadPool.QueueUserWorkItem(x => {
Console.WriteLine(x);
events[j].Set();
}, list[i]);
}
WaitHandle.WaitAll(events);
答案 3 :(得分:1)
线程池不会告诉您线程何时完成执行,因此工作项必须自己执行。我改变了这样的代码:
var list = new List<int>();
ManualResetEvent[] handles = new ManualResetEvent[10];
for (int i = 0; i < 10; i++) {
list.Add(i);
handles[i] = new ManualResetEvent(false);
}
for (int i = 0; i < 10; i++) {
ThreadPool.QueueUserWorkItem(
new WaitCallback(x =>
{
Console.WriteLine(x);
handles[(int) x].Set();
}), list[i]);
}
WaitHandle.WaitAll(handles);
答案 4 :(得分:0)
我就是这样做的。
class Program
{
static void Main(string[] args)
{
var items = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
using (var countdown = new Countdown(items.Length))
{
foreach (var item in items)
{
ThreadPool.QueueUserWorkItem(o =>
{
Thread.SpinWait(100000000);
Console.WriteLine("Thread Done!");
countdown.Signal();
});
}
countdown.Wait();
}
Console.WriteLine("Job Done!");
Console.ReadKey();
}
public class Countdown : IDisposable
{
private readonly ManualResetEvent done;
private readonly int total;
private volatile int current;
public Countdown(int total)
{
this.total = total;
current = total;
done = new ManualResetEvent(false);
}
public void Signal()
{
lock (done)
{
if (current > 0 && --current == 0)
done.Set();
}
}
public void Wait()
{
done.WaitOne();
}
public void Dispose()
{
done.Dispose();
}
}
}
答案 5 :(得分:-1)
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(xyz));
}
bool working = true;
ThreadPool.GetMaxThreads(out int maxWorkerThreads, out int maxCompletionPortThreads);
while (working)
{
ThreadPool.GetAvailableThreads(out int workerThreads, out int completionPortThreads);
//Console.WriteLine($"{workerThreads} , {maxWorkerThreads}");
if (workerThreads == maxWorkerThreads)
{ working = false; }
}
//when all threads are completed then 'working' will be false
}
void xyz(object o)
{
console.writeline("");
}