我有3个线程,两个“ worker ”和一个“经理”。 “Workers”线程等待EventWaitHandle,在增加它们的计数器之后,“manager”线程将向EventWaitHandle发出信号。
这些“ worker ”线程之间的唯一区别是,一个使用EventWaitHandle.WaitAny(),另一个使用EventWaitHandle.WaitOne()

这是代码:

class Program
{
    static void Main(string[] args)
    {
        MultiThreadedJobs multyThreadedJobs = new MultiThreadedJobs();
        multyThreadedJobs.Start();

        Console.ReadLine();

        multyThreadedJobs.Stop();
    }
}

class MultiThreadedJobs : IDisposable
{
    private EventWaitHandle syncEvent;
    private EventWaitHandle[] syncEventsArray;

    private Thread managerThread;
    private Thread firstWorkerThread;
    private Thread secondWorkerThread;

    private volatile bool running = false;


    public MultiThreadedJobs() // Ctor
    {
        syncEvent = new EventWaitHandle(false, EventResetMode.AutoReset, "JobsSyncEvent");

        syncEventsArray = new EventWaitHandle[1];
        syncEventsArray[0] = syncEvent;

        managerThread = new Thread(ManagerThreadMethod);
        firstWorkerThread = new Thread(FirstWorkerThreadMethod);
        secondWorkerThread = new Thread(SecondWorkerThreadMethod);
    }

    public void Start()
    {
        running = true;

        managerThread.Start();
        firstWorkerThread.Start();
        secondWorkerThread.Start();
    }

    public void Stop()
    {
        running = false;
    }

    private void ManagerThreadMethod() // Manager Thread
    {
        while (running)
        {
            Thread.Sleep(1000);
            syncEvent.Set();
        }
    }

    private void FirstWorkerThreadMethod() // Worker Thread
    {
        int counter = 0;
        while (running)
        {
            syncEvent.WaitOne();
            counter++;
        }
    }

    private void SecondWorkerThreadMethod() // Worker Thread
    {
        int counter = 0;
        while (running)
        {
            EventWaitHandle.WaitAny(syncEventsArray);
            counter++;
        }
    }

    public void Dispose()
    {
        syncEvent.Close();
    }
}

问题是,只有带有EventWaitHandle.WaitAny()的第二个工作线程总是捕获事件,并使第一个工作线程饿死。而不是每个人的50/50%。

最佳答案

您正在寻找解决软件工程中非常普遍的问题Producer-consumer problem的解决方案。链接的Wikipedia文章上有不错的背景信息,特别是显示了如何以错误的方式进行操作。

您肯定是在寻求错误的解决方案。 AutoResetEvent太简单了。您已经发现了一个问题,它没有提供公平性。它的许多其他问题,特别是当生产者线程比消费者线程更快地生成作业时,它遭受了讨厌的线程竞赛。

示例代码过于人为,无法提供一个很好的选择。底层锁定可以通过ReaderWriterLock/Slim类实现。 .NET 4 BlockingCollection类特别适合解决生产者/消费者问题。支持任意数量的生产者线程和使用者线程,并提供限制以确保在消费者无法跟上生产者时,程序不会崩溃。您可以使用从生产者传递给使用者线程的伪造“ token ”来重写样本。 BlockingColletion<bool>完成工作。

09-11 17:58