C# 什么';等待信号灯的正确方式是什么?

C# 什么';等待信号灯的正确方式是什么?,c#,.net,multithreading,semaphore,waithandle,C#,.net,Multithreading,Semaphore,Waithandle,我认为下面的代码将让所有10个线程运行,一次运行两个线程,然后在调用Release()10次后打印“done”。但事实并非如此: int count = 0; Semaphore s = new Semaphore(2, 2); for (int x = 0; x < 10; x++) { Thread t = new Thread(new ThreadStart(delegate()

我认为下面的代码将让所有10个线程运行,一次运行两个线程,然后在调用
Release()
10次后打印“done”。但事实并非如此:

        int count = 0;

        Semaphore s = new Semaphore(2, 2);
        for (int x = 0; x < 10; x++)
        {
            Thread t = new Thread(new ThreadStart(delegate()
            {
                s.WaitOne();
                Thread.Sleep(1000);
                Interlocked.Increment(ref count);                       
                s.Release();
            }));
            t.Start(x);
        }

        WaitHandle.WaitAll(new WaitHandle[] { s });
        Console.WriteLine("done: {0}", count);
如果实现我正在寻找的功能的唯一方法是将一个
EventWaitHandle
传递给每个线程,然后对这些
EventWaitHandles
数组执行一个
WaitAll()
,那么对一个只有信号量的数组执行
WaitAll()
有什么意义?换句话说,等待线程何时解除阻塞?

WaitHandle.WaitAll(新的WaitHandle[]{s})像s.WaitOne()一样等待。它一有机会就进入。您似乎期望此调用等待所有其他信号量操作,但操作系统无法区分这两者之间的区别。这个命令很可能是第一个被授权访问信号量的命令


我想你需要的是
屏障
类。它是为fork-join样式的并行而设计的。

WaitHandle.WaitAll
只是等待,直到所有处理程序都处于信号状态

因此,当您在one上调用
WaitHandle.WaitAll
WaitHandle
时,它的工作原理与调用
s.WaitOne()

例如,您可以使用以下代码等待所有已启动的线程,但允许两个线程并行运行:

int count = 0;

Semaphore s = new Semaphore(2, 2);
AutoResetEvent[] waitHandles = new AutoResetEvent[10];
for (int x = 0; x < 10; x++)
    waitHandles[x] = new AutoResetEvent(false);

for (int x = 0; x < 10; x++)
{
    Thread t = new Thread(threadNumber =>
        {
            s.WaitOne();
            Thread.Sleep(1000);
            Interlocked.Increment(ref count);
            waitHandles[(int)threadNumber].Set();
            s.Release();
        });
    t.Start(x);
}

WaitHandle.WaitAll(waitHandles);
Console.WriteLine("done: {0}", count);
int count=0;
信号量s=新信号量(2,2);
AutoResetEvent[]waitHandles=新的AutoResetEvent[10];
对于(int x=0;x<10;x++)
waitHandles[x]=新的自动重置事件(false);
对于(int x=0;x<10;x++)
{
线程t=新线程(线程编号=>
{
s、 WaitOne();
睡眠(1000);
联锁增量(参考计数);
waitHandles[(int)threadNumber].Set();
s、 释放();
});
t、 启动(x);
}
WaitHandle.WaitAll(waitHandles);
WriteLine(“完成:{0}”,计数);

很可能您看到的是局部竞争条件
Console.WriteLine在其周围有自己的锁,并且不能保证内容的输出顺序与调用它的顺序相同。您可能希望编写勾号值或使用更好地处理这种情况的日志框架。输出没有显示两个线程在同一时间两个线程不同时运行。只是FIY,您可能需要考虑使用<代码>互锁。增量< /COD>而不是<代码> Value:CasPRONE,我不确定是否正确,因为我用同样的问题来处理同样的问题,即使我用Studio.CycTys.Debug .WrdWrand替换最后一行。(“完成”);我真的不确定这个例子的要点是什么-反正你要开始10个线程。如果你想一次运行两个线程,为什么不只打开两个线程并平均分配工作。如果你想等待所有线程完成,请保留
线程
对象,并依次对每个线程调用
连接
。@caesay the Barrier类当然在网上有很多教程,很容易使用。
int count = 0;

Semaphore s = new Semaphore(2, 2);
AutoResetEvent[] waitHandles = new AutoResetEvent[10];
for (int x = 0; x < 10; x++)
    waitHandles[x] = new AutoResetEvent(false);

for (int x = 0; x < 10; x++)
{
    Thread t = new Thread(threadNumber =>
        {
            s.WaitOne();
            Thread.Sleep(1000);
            Interlocked.Increment(ref count);
            waitHandles[(int)threadNumber].Set();
            s.Release();
        });
    t.Start(x);
}

WaitHandle.WaitAll(waitHandles);
Console.WriteLine("done: {0}", count);