C# 安全地限制并行Foreach循环中的类调用数量
我有一个简单的foreach循环,它根据while循环和一个静态int来限制自己。如果我不限制它,我的CPU将保持在10%以下,如果我限制它,我的CPU将上升到99/100%。如何安全地限制Paralell.Foreach中类的调用数量C# 安全地限制并行Foreach循环中的类调用数量,c#,multithreading,C#,Multithreading,我有一个简单的foreach循环,它根据while循环和一个静态int来限制自己。如果我不限制它,我的CPU将保持在10%以下,如果我限制它,我的CPU将上升到99/100%。如何安全地限制Paralell.Foreach中类的调用数量 static int ActiveThreads { get; set; } static int TotalThreads { get; set; } var options = new ParallelOptions(); options.MaxDegre
static int ActiveThreads { get; set; }
static int TotalThreads { get; set; }
var options = new ParallelOptions();
options.MaxDegreeOfParallelism = 1;
Parallel.ForEach(urlTable.AsEnumerable(),options,drow =>
{
using (var WCC = new MasterCrawlerClass())
{
while (TotalThreads <= urlTable.Rows.Count)
{
if (ActiveThreads <= 9)
{
Console.WriteLine("Active Thread #: " + ActiveThreads);
ActiveThreads++;
WCC.MasterCrawlBegin(drow);
TotalThreads++;
Console.WriteLine("Done Crawling a datarow");
ActiveThreads--;
}
}
}
});
static int-ActiveThreads{get;set;}
静态整型TotalThreads{get;set;}
var options=新的ParallelOptions();
options.MaxDegreeOfParallelism=1;
Parallel.ForEach(urlTable.AsEnumerable(),选项,drow=>
{
使用(var WCC=new MasterCrawlerClass())
{
而(TotalThreads有两件事:
1) 您似乎没有使用在本例中创建的ParallelOptions()
2) 如果出于某种原因不想使用并行选项,则可以使用信号灯
Semaphore sm = new Semaphore(0, 9);
// increment semaphore or block if = 9
// this will block gracefully without constantly checking for `ActiveThreads <= 9`
sm.WaitOne();
// decrement semaphore
sm.Release();
Semaphore sm=新的信号量(0,9);
//增量信号量或块(如果=9)
//这将在不经常检查'ActiveThreads'的情况下优雅地阻止
我有一个简单的foreach循环,它基于while循环限制自己
和一个静态int。如果我不限制它,如果我
限制它我的CPU上升到99/100%
这很奇怪。这可能是因为您限制了与循环的并发性,顺便说一句,这似乎导致每个drow
都被爬网了很多次。我怀疑这是您想要的。爬网操作是IO限制的,所以CPU利用率很低
如果确实要将对mastercrawlbeagin
的并发调用数限制为9,则将MaxDegreesOfParallelism=9
。while
和TotalThreads
和ActiveThreads
的循环和维护将不起作用。请注意,在m中增加和减少计数器非线程安全的退火
将代码更改为如下所示
int ActiveThreads = 0;
var options = new ParallelOptions();
options.MaxDegreeOfParallelism = 9;
Parallel.ForEach(urlTable.AsEnumerable(),options,drow =>
{
int x = Interlocked.Increment(ref ActiveThreads);
Console.WriteLine("Active Thread #: " + x);
try
{
using (var WCC = new MasterCrawlerClass())
{
WCC.MasterCrawlBegin(drow);
}
}
finally
{
Interlocked.Decrement(ref ActiveThreads);
Console.WriteLine("Done Crawling a datarow");
}
});
您似乎没有将ParallelOptions(options变量)传递给Parallel.ForEach(它应该滑入第一个和第二个参数之间)。否则您将如何限制并行性?@yamen即使我通过了限制它的选项,也会在它停止创建之前达到阈值threads@yamen我试图限制它在任何时候进入这个类的次数如果你想限制进入一个特定的类,你可以用信号量来控制这个类,但不是真的100%清楚你想在这里实现什么。也许可以提供一个更完整的代码示例?我不能使用ParallelOptions,我拿出选项进行测试,在开关打开之前,Paralleloption=1的阈值从未达到,所以我必须限制访问classA信号量的次数。根据定义,classA信号量似乎是一个答案t正是这样做的——它保护了关键的section@xavier也许是个愚蠢的问题,但是我应该把sm.WaitOne()放在哪里?它在ForeachLoop中吗?@Mike如果我没有弄错你的问题,那么你在foreach之前创建一个信号量,在调用类之前放置sm.WaitOne()。在调用之后放置sm.Release()您完成了。@xavier谢谢,您能用我上面的内容提供一个示例吗?我尝试将sm.WaitOne()放在类调用之前,但它实际上从未通过sm.WaitOne()