【问题标题】:A function that only permits N concurrent threads只允许 N 个并发线程的函数
【发布时间】:2012-04-27 22:43:08
【问题描述】:

我有一个 Visual Studio 2008 C# .NET 3.5 项目,其中一个类侦听来自另一个多线程类的事件调用。我需要确保我的事件只允许同时访问最多 10 个线程。第 11 个线程应该阻塞,直到 10 个线程之一完成。

myobj.SomeEvent += OnSomeEvent;

private void OnSomeEvent(object sender, MyEventArgs args)
{
    // allow up to 10 threads simultaneous access. Block the 11th thread.
    using (SomeThreadLock lock = new SomeThreadLock(10))
    {         
        DoUsefulThings(args.foo);
    }
}

我无法控制另一个 MyObj 类,因此我无法在那里实现线程池。

实现这一点的最佳方法是什么?

谢谢, 保罗H

【问题讨论】:

    标签: c# multithreading .net-3.5


    【解决方案1】:

    你想要Semaphore class。简而言之,它是一个在任何时候只允许指定数量的调用者通过的锁。

    由于您不控制线程的创建,因此您需要小心死锁情况。信号量不是可重入感知的——如果给定线程多次进入一个信号量,它将占用多个槽。因此,如果您的调用者的每个线程多次进入您的信号量,就有可能出现死锁。

    【讨论】:

      【解决方案2】:

      为此使用Semaphore。构造函数参数对于那些刚刚被引入类的人来说有点混乱。第一个参数指定现在允许通过的初始线程数。第二个参数指定在任何给定时间允许通过的最大线程数。

      myobj.SomeEvent += OnSomeEvent;
      Semaphore semaphore = new Semaphore(10, 10);
      
      private void OnSomeEvent(object sender, MyEventArgs args)
      {
        semaphore.WaitOne();
        try
        {
          DoUsefulThings(args.foo);
        }
        finally
        {
          semaphore.Release();
        }
      }
      

      【讨论】:

      • +1 表示您应该退出 try/catch 的 finally 块中的信号量。这很重要——万一你的代码抛出异常,你要确保信号量已经退出。
      【解决方案3】:

      通常为此使用信号量。将其初始化为 10 个单位。在 DoUsefulThings() 之前 wait() 一个单元,之后一个单元 signal() 。

      【讨论】:

        猜你喜欢
        • 2016-10-01
        • 2023-01-16
        • 2019-07-17
        • 2021-03-01
        • 2017-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-24
        相关资源
        最近更新 更多