并行库:对一个并行度进行延迟,将所有并行度延迟
本文关键字:延迟 并行度 一个 并行 | 更新日期: 2023-09-27 18:26:58
我有一个ConcurrentBag urls
,它的项目正在并行处理(没有任何内容写回集合):
urls.AsParallel<UrlInfo>().WithDegreeOfParallelism(17).ForAll( item =>
UrlInfo info = MakeSynchronousWebRequest(item);
(myProgress as IProgress<UrlInfo>).Report(info);
});
我在网络请求中将超时设置为30秒。当遇到响应非常慢的url时,所有的并行处理都会停止。这是预期的行为,还是我应该在代码中查找一些问题?
进展如下:
myProgress = new Progress<UrlInfo>( info =>
{
Action action = () =>
{
Interlocked.Increment(ref itested);
if (info.status == UrlInfo.UrlStatusCode.dead)
{
Interlocked.Increment(ref idead);
this.BadUrls.Add(info);
}
dead.Content = idead.ToString();
tested.Content = itested.ToString();
};
try
{
Dispatcher.BeginInvoke(action);
}
catch (Exception ex)
{
}
});
这是预期的行为。AsParallel
直到所有操作完成才返回。由于您正在进行同步请求,您必须等到最慢的请求完成。然而,请注意,即使您有一个非常慢的任务占用了一个线程,调度器也会继续调度新任务,因为旧任务在剩余线程上完成。
这里有一个很有启发性的例子。它创建了101个任务。第一个任务占用一个线程5000毫秒,其他100个任务占用其余20个线程各1000毫秒。因此,它安排了其中20个任务,每个任务运行一秒钟,经过5次循环,完成所有100个任务,总共5000毫秒。然而,如果你把101改为102,这意味着你有101个任务在20个线程上翻腾,最终需要6000毫秒;直到5秒,第101个任务才有一个线程可以继续执行。如果你把101改为2,你会注意到它仍然需要5000毫秒,因为你必须等待缓慢的任务完成。
static void Main()
{
ThreadPool.SetMinThreads(21, 21);
var sw = new Stopwatch();
sw.Start();
Enumerable.Range(0, 101).AsParallel().WithDegreeOfParallelism(21).ForAll(i => Thread.Sleep(i==0?5000:1000));
Console.WriteLine(sw.ElapsedMilliseconds);
}