【问题标题】:Semaphore WaitOne not operating correctly信号量 WaitOne 无法正常运行
【发布时间】:2012-04-12 10:22:00
【问题描述】:

我有一个信号量,假设限制为 3,但是,它只是不停地调用它想要的数量。我假设这是因为我使用(1000)。但是,当我只尝试 () 时,它永远不会通过 WaitOne 我不确定在这里做什么。

private static Semaphore _pool;
_pool = new Semaphore(0, 3);
var options = new ParallelOptions();
options.MaxDegreeOfParallelism = 1;
Parallel.ForEach(urlTable.AsEnumerable(),options, drow =>
{
    using (var WCC = new MasterCrawlerClass())
    {
                ActiveThreads++;
                _pool.WaitOne(1000);
                Console.WriteLine("Active Thread #: " + ActiveThreads);
                WCC.MasterCrawlBegin(drow);
                Console.WriteLine("Done Crawling a datarow");
                ActiveThreads--;
                _pool.Release();

    }
});

【问题讨论】:

  • 看到你将 maxdop 设置为 1,Parallel.ForEach 的用途实际上在这里给你买了什么?循环体也可能在线程池中运行,其中阻塞代码是一个很大的禁忌。您还应该防范对 ActiveThreads 的并发访问。你能解释一下你想在这里做什么吗?可能有更好的方法。
  • @spender 我想做的就是限制 Parallel.Foreach 实际调用 WCC 的次数
  • 限制在什么范围内?最多 3 次并发抓取?
  • @spender 是的,那很好,但我真的只想说 int = ;以及任何限制

标签: c# multithreading semaphore


【解决方案1】:

您对信号量的构造有误。应该是_pool = new Semaphore(3, 3); 这样做还可以消除将超时参数传递给WaitOne() 的需要。

第一个参数是在阻塞之前可能被授予的初始请求数,因此传递 0 意味着任何后续对 WaitOne() 的调用将立即阻塞。

【讨论】:

  • 这可能只是因为我不明白,但不是第一个 Int intial count 吗?我想要0,然后继续直到我有3,第二个int是最大值,所以应该是(0,3)
  • @Mike 这是可能被授予的初始计数;将其设置为 0 意味着“您最初可以在阻塞之前授予 0 个请求”,这显然不是您想要的。
  • 这可能不是我想要的,在我的 foreach 循环中它只会进入一个循环,无论我将其更改为 (3,3) 还是 (4,8) 为什么会这样
  • @Mike:因为你设置了MaxDegreeOfParallelism = 1?
【解决方案2】:

这里有一些问题。

  • 我怀疑首先在这种情况下没有理由限制并发。
  • 您在Semaphore 构造函数中将initialCount 设置为0。 initialCount现在可以授予的请求数。
  • 您正在使用接受超时参数的WaitOne 的重载。当超时到期时,WaitOne 将返回,无论是否从信号量中获取计数。
  • 您正在递增ActiveThreads从信号量中进行计数。这意味着ActiveThreads 更接近于ForEach 操作的同时工作线程数。它不会告诉你有多少线程正在执行MasterCrawlBegin
  • ActiveThreads 上的 ++ 操作不是线程安全的。
  • 您将MaxDegreesOfParallelism 设置为一个几乎可以消除任何类型的并发处理的值。

更改您的代码,使其看起来像这样。

int ActiveThreads = 0;
int ActiveCrawls = 0;
var semaphore = new SemaphoreSlim(3, 3); 
Parallel.ForEach(urlTable.AsEnumerable(), drow => 
  { 
    int x = Interlocked.Increment(ref ActiveThreads);
    Console.WriteLine("Active Thread #: " + x); 
    semaphore.Wait();
    int y = Interlocked.Increment(ref ActiveCrawls);
    Console.WriteLine("Active Crawl #: " + y); 
    try
    {
      using (var WCC = new MasterCrawlerClass()) 
      { 
        WCC.MasterCrawlBegin(drow);
      }
    }
    finally
    {
      Interlocked.Decrement(ref ActiveCrawls);
      semaphore.Release();
      Interlocked.Decrement(ref ActiveThreads);
      Console.WriteLine("Done Crawling a datarow"); 
    }
  } 
}); 

当然,您可以只设置MaxDegreesOfParallelism = 3 而不必担心所有信号量的东西。

【讨论】:

  • 请参阅我的answer 此处以进一步分析您的问题以及我认为在这种情况下限制并行性是一个坏主意的原因。
猜你喜欢
  • 2017-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-12
  • 1970-01-01
  • 2019-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多