所以根据MSDN以及我读过的许多其他地方,他们在各个线程中使用信号量并阻塞,如下所示:
private static Semaphore _pool;
public static void Main()
{
_pool = new Semaphore(0, 3);
for(int i = 1; i <= 1000; i++)
{
Thread t = new Thread(new ParameterizedThreadStart(Worker));
t.Start(i);
}
}
private static void Worker(object num)
{
try
{
_pool.WaitOne();
// do a long process here
}
finally
{
_pool.Release();
}
}
根据Main()中的迭代次数,阻止进程是不是更有意义,以便不会同时创建可能的1000个线程?例如:
private static Semaphore _pool;
public static void Main()
{
_pool = new Semaphore(0, 3);
for(int i = 1; i <= 1000; i++)
{
_pool.WaitOne(); // wait for semaphore release here
Thread t = new Thread(new ParameterizedThreadStart(Worker));
t.Start(i);
}
}
private static void Worker(object num)
{
try
{
// do a long process here
}
finally
{
_pool.Release();
}
}
也许两种方式都没有错,这取决于具体情况?或者,一旦有很多迭代,有更好的方法可以做到这一点吗?
编辑:这是一个Windows服务,所以我没有阻止UI线程。
答案 0 :(得分:2)
您通常在线程中执行此操作的原因是您希望使该独占部分尽可能小。您不需要整个线程同步,只需要该线程访问共享资源。
所以更真实的工作版本是
private static void Worker(object num)
{
//Do a bunch of work that can happen in parallel
try
{
_pool.WaitOne();
// do a small amount of work that can only happen in 3 threads at once
}
finally
{
_pool.Release();
}
//Do a bunch more work that can happen in parallel
}
(PS如果您正在做一些使用1000个线程的事情,那么您做错了什么。您可能宁愿使用ThreadPool或Tasks来处理许多短期工作负载或让每个线程都做更多的工作。)
以下是使用Parallel.ForEach
的方法private static BlockingCollection<int> _pool;
public static void Main()
{
_pool = new BlockingCollection<int>();
Task.Run(() => //This is run in another thread so it shows data is being taken out and put in at the same time
{
for(int i = 1; i <= 1000; i++)
{
_pool.Add(i);
}
_pool.CompleteAdding(); //Lets the foreach know no new items will be showing up.
});
//This will work on the items in _pool, if there is no items in the collection it will block till CompleteAdding() is called.
Parallel.ForEach(_pool.GetConsumingEnumerable(), new ParallelOptions {MaxDegreeOfParallelism = 3}, Worker);
}
private static void Worker(int num)
{
// do a long process here
}