c#多个可重用的工作线程

本文关键字:工作 线程 | 更新日期: 2023-09-27 18:06:38

我试图用可重用的工作线程构建某种多线程游戏引擎。这意味着工作线程正在运行一个无限循环,并且在每次迭代之后,调用一个方法,该方法使用AutoResetEvent挂起线程,直到下一次迭代从外部开始。效果很好。但是我想等待所有的工作线程进入等待状态。但是最后一个线程总是在第一步中被忽略。这是我的代码:

class WorkerThread
{
    private readonly Game game;
    private readonly Task task;
    private readonly AutoResetEvent waitEvent;
    private readonly AutoResetEvent finishEvent;
    public string Message { get; set; }
    public bool Active { get; private set; }
    public WorkerThread(Game game)
    {
        this.game = game;
        waitEvent = new AutoResetEvent(false);
        finishEvent = new AutoResetEvent(false);
        task = new Task(startTask);
    }
    public void Start()
    {
        task.Start();
    }
    public void PerformFrame()
    {
        finishEvent.Reset();
        waitEvent.Set();
    }
    public void WaitForFrameToFinish()
    {
        finishEvent.WaitOne();
    }
    private void startTask()
    {
        WaitFrame();
        run();
    }
    long sum;
    private void run()
    {
        while (true)
        {
            sum = 0;
            for (int i = 0; i < 1000000; i++)
            {
                sum += i;
            }
            Console.WriteLine(Message);
            WaitFrame();
        }
    }
    private void WaitFrame()
    {
        Active = false;
        finishEvent.Set();
        waitEvent.WaitOne();
        Active = true;
    }
}
class Game
{
    private readonly List<WorkerThread> workers = new List<WorkerThread>();
    public Game()
    {
        workers.Add(new WorkerThread(this) { Message = "Worker 1" });
        workers.Add(new WorkerThread(this) { Message = "Worker 2" });
        workers.Add(new WorkerThread(this) { Message = "Worker 3" });
        workers.Add(new WorkerThread(this) { Message = "Worker 4" });
        workers.Add(new WorkerThread(this) { Message = "Worker 5" });
        workers.Add(new WorkerThread(this) { Message = "Worker 6" });
    }
    public void Start()
    {
        foreach (WorkerThread worker in workers)
        {
            worker.Start();
        }
    }
    public void OneFrame()
    {
        //start every worker
        foreach (WorkerThread worker in workers)
        {
            worker.PerformFrame();
        }
        //wait for the workers to finish
        foreach (WorkerThread worker in workers)
        {
            worker.WaitForFrameToFinish();
        }
        //check if there are workers still running
        foreach (WorkerThread worker in workers)
        {
            if (worker.Active)
            {
                Console.WriteLine(worker.Message + " still active");
            }
        }
        Console.WriteLine("Frame finished.'n");
    }
}

有没有人知道为什么Game不等待最后一个WorkerThread完成它的任务?

编辑:使用ManualResetEventSlim代替AutoResetEvent解决了问题。但我还是不明白为什么上面的方法不管用。

编辑2:我找到了答案并贴在了下面。

c#多个可重用的工作线程

我刚刚找到了解决方案。startTask使用WaitFrame方法来设置finishEvent。这样WaitForFrameToFinish就不会在第一次迭代时等待worker,因为finishEvent已经设置好了。如果你这样做,它工作得很好:

private void startTask()
{
    waitEvent.WaitOne();
    waitEvent.Reset();
    finishEvent.Reset();
    run();
}