请考虑以下代码。我不想创建class Waiter
的多个实例。 (所以我不能使用ManualResetEvent类)
using System;
using System.Threading;
public class Waiter
{
static int counter=0;
static int max=20;
public void Start()
{
for (int i = 1; i <= max; i++)
{
ThreadPool.QueueUserWorkItem(DoWork, (object)i);
}
Console.Read();//without this line the application quits before all threads are complete :(
}
public void DoWork(object o)
{
try
{
Thread.Sleep(1000);
}
finally
{
counter++;
Console.WriteLine(counter);
if (counter==max )
{
Console.WriteLine("All threads complete");
}
}
}
}
public class ThreadPoolExample
{
static void Main()
{
Waiter wtr=new Waiter();
wtr.Start();
}
}
我对上面的代码有两个问题
1&gt;没有Console.Read()
应用程序在所有线程结束之前退出。
2&gt;语句Console.WriteLine("All threads complete");
执行两次。
我该如何解决这个问题?
答案 0 :(得分:3)
改为使用Tasks,然后您可以执行Task.WaitAll(tasks);
此外,通过工厂实例化您的任务:
Task.Factory.StartNew(() => { Console.Writeline(""); });
它将为您使用线程池。
答案 1 :(得分:0)
您应该使用Interlocked.Increment来增加counter
。因为当两个线程试图同时递增它时存在竞争条件。
如果您想让多个Writer
实例同时工作,那么您就不能拥有静态counter
变量。他们会互相争斗。只需将其设为私有实例变量即可。 Max应该是const
或readonly
(并保持静态),如果它永远不会改变,或者它也应该是一个实例字段,如果它可以改变。
最后,如果你有一个非静态ManualResetEvent
实例,你可以在Start
中创建它,初始化它以设置,在循环结束时等待它,然后在最后一个线程完成(你当前只是写入控制台)。