离开 WaitOne 时获取锁定

本文关键字:锁定 获取 WaitOne 离开 | 更新日期: 2023-09-27 18:32:07

我有一个像这样实现的任务调度程序:

  private readonly List<Task> mTasks = new List<Task>();
  private readonly ManualResetEvent mNoTaskEvent = new ManualResetEvent(false);
  public void AddTask(Task task)
  {
     lock (mTasks)
     {
        mTasks.Add(task);
        mNoTaskEvent.Set();
     }
  }
  public void RemoveTask(Task task)
  {
     lock (mTasks)
     {
        mTasks.Remove(task);
        if (mTasks.Count == 0)
           mNoTaskEvent.Reset();
     }
  }
  void BackgroundThreadProc()
  {
     while (mRunning)
     {
        mNoTaskEvent.WaitOne();
        if (!mRunning) break;
        Task nextTask;
        lock (mTasks)
        {
           mTasks.Sort(...);
           nextTask = mTasks.First();
        }
        nextTask.Run();
     }
  }

mNoTaskEvent 允许在没有可用任务时阻止后台线程。如果另一个线程删除"mNoTaskEvent.WaitOne()"和"lock(mTasks)"之间的所有剩余任务,则存在竞争条件。

离开 mNoTaskEvent.WaitOne() 时,我怎样才能原子地获取 mTasks 锁?

编辑pthread API 有一个函数,可以完全满足我的需要: pthread_cond_wait

离开 WaitOne 时获取锁定

竞争条件的简单解决方法是再次检查计数:

    lock (mTasks)
    {
       if (mTasks.Count < 1)
         continue;
       mTasks.Sort(...);
       nextTask = mTasks.First();
    }

使用 Monitor.Wait():

 while (mRunning)
 {
    //mNoTaskEvent.WaitOne();
    if (!mRunning) break;
    Task nextTask;
    lock (mTasks)
    {
        while (mTasks.Count < 1)
        {
           Monitor.Wait(mTasks);
           if (!mRunning) break;                
        }
        ...     
    }

public void AddTask(Task task)
{
  lock (mTasks)
  {
     mTasks.Add(task);
     //mNoTaskEvent.Set();
     Monitor.Pulse(mTasks);
  }
}

停止整个链时,您还需要 Pulse()。