2

我有一个信号量限制为 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();

    }
});
4

2 回答 2

6

你在误解信号量。应该_pool = new Semaphore(3, 3);这样做也将消除将超时参数传递给WaitOne().

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

于 2012-04-12T00:32:46.873 回答
3

这里有几个问题。

  • 我怀疑首先在这种情况下没有理由限制并发性。
  • 您在构造函数中设置initialCount为 0 。是现在可以授予的请求数。SemaphoreinitialCount
  • 您正在使用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而不用担心所有信号量的东西。

于 2012-04-12T02:00:33.323 回答