需要了解SemaphoreSlim的用法

时间:2013-11-18 20:02:53

标签: c# multithreading task-parallel-library semaphore

这是我的代码,但我不明白SemaphoreSlim在做什么。

async Task WorkerMainAsync()
{
  SemaphoreSlim ss = new SemaphoreSlim(10);
  List<Task> trackedTasks = new List<Task>();
  while (DoMore())
  {
    await ss.WaitAsync();
    trackedTasks.Add(Task.Run(() =>
              {
                DoPollingThenWorkAsync();
                ss.Release();
              }));
  }
  await Task.WhenAll(trackedTasks);
}

void DoPollingThenWorkAsync()
{
  var msg = Poll();
  if (msg != null)
  {
    Thread.Sleep(2000); // process the long running CPU-bound job
  }
}

等待ss.WaitAsync(); & ss.Release();做什么?

我想如果我一次运行50个线程然后编写像SemaphoreSlim ss = new SemaphoreSlim(10);这样的代码,那么它将被强制运行10个活动线程。

当10个线程中的一个完成后,另一个线程将启动....如果我不对,那么请帮助我理解样本情况。

为什么await需要与ss.WaitAsync();一起使用? ss.WaitAsync();做了什么?

3 个答案:

答案 0 :(得分:48)

  

我想如果我一次运行50个线程,那么代码就像SemaphoreSlim ss = new SemaphoreSlim(10);将强制在时间运行10个活动线程

这是正确的;信号量的使用确保了不会有超过10名工人同时从事这项工作。

在信号量上调用WaitAsync会产生一个任务,当该线程被赋予对该令牌的“访问权限”时,该任务将完成。 await - 该任务允许程序在“允许”的情况下继续执行。拥有异步版本,而不是调用Wait,对于确保方法保持异步而不是同步,以及处理async方法可以执行代码的事实非常重要几个线程,由于回调,因此与信号量的自然线程亲和力可能是一个问题。

旁注:DoPollingThenWorkAsync不应该有Async后缀,因为它实际上不是异步的,而是同步的。只需将其称为DoPollingThenWork即可。它将减少读者的困惑。

答案 1 :(得分:2)

虽然我接受这个问题确实与倒计时锁定方案有关,但我认为值得分享我为那些希望将SemaphoreSlim用作简单异步锁的人所发现的链接。它允许您使用using语句,这可以使编码更整洁,更安全。

http://www.tomdupont.net/2016/03/how-to-release-semaphore-with-using.html

我确实在它的Dispose周围交换_isDisposed=true_semaphore.Release(),以防万一它被多次调用。

同样重要的是要注意SemaphoreSlim不是可重入锁定,这意味着如果同一个线程多次调用WaitAsync,则信号量每次都会递减计数。简而言之,SemaphoreSlim不是线程感知的。

关于代码质量的问题,最好将Release放在try-finally的finally中,以确保它始终被释放。

答案 2 :(得分:1)

在拐角处的幼儿园,他们使用SemaphoreSlim控制可在体育室玩多少个孩子。

他们在房间外面的地板上画了5对脚印。

孩子们到达时,他们把鞋子放在一双免费的脚印上,进入房间。

玩完游戏后,他们就会出来,收拾鞋子,为另一个孩子“释放”一个插槽。

如果孩子到了并且没有脚印了,他们会去别处玩或者呆一会儿,然后不时检查一下(即,没有FIFO优先级)。

当老师在附近时,她在走廊的另一侧“释放”额外的5个脚印行,以使另外5个孩子可以同时在房间里玩耍。

它也具有SemaphoreSlim的“陷阱” ...

如果一个孩子完成游戏并且离开房间而没有拿起鞋子(不会触发“释放”),则即使理论上有一个空的插槽,插槽也会被阻塞。通常,孩子通常会被告知。

有时候,一个或两个偷偷摸摸的孩子将鞋子藏在别处,然后进入房间,即使所有的脚印都已被占用(即SemaphoreSlim并不能“真正”控制房间里有多少个孩子)。

这通常不会很好地结束,因为房间过度拥挤往往会因孩子哭泣和老师完全关闭房间而结束。