2

我有一个贯穿 500.000ish 列表的 for 循环。对于其中的每一个,它都在排队一个 SmartThreadPool 作业。

lines.Length下面包含 500.000ish 项目。

我的问题是我在一次将它们全部排队时遇到内存问题。所以我虽然写了一个逻辑来防止这种情况:

int activeThreads = _smartThreadPool2.ActiveThreads;
if (activeThreads < maxThreads) 
{
    int iia = 0;
    for (int i = 0; i < lines.Length; i++)
    {
        if (doNotUseAdditive.Checked == true)
        {
            foreach (string engine in _checkedEngines) // Grab selected engines
            {
                query = lines[i];

                _smartThreadPool2.QueueWorkItem(
                new Amib.Threading.Func<string, string, int, int, int>(scrape),
                query, engine, iia, useProxies);

                iia++;
            }
        }
    }
}
else
{
    // Wait
    wait.WaitOne();
}

问题是我无法在我的 for 循环中运行该 if 语句,因为当我回到它时,它不会记住它在循环中的位置。

我正在使用:

ManualResetEvent wait = new ManualResetEvent(false);  //global variable

到“暂停/恢复”

我需要在使用 X 线程后以某种方式暂停循环,然后当线程可用时返回并继续循环。

有任何想法吗?

4

1 回答 1

3

我认为在单独的线程中处理列表中的每个项目并不是一个好主意。即使使用自定义线程池也很容易出错(你的例子证明了我的观点)。

首先,您应该正确确定工作线程的数量。看来您正在处理计算密集型操作(所谓的 CPU 绑定操作),您应该使用工作线程数等于逻辑处理器数。

您可以使用Parallel LINQ将所有工作集拆分为适当数量的块并并行处理这些块。

Joe Albahari 有一系列关于这个主题的精彩文章:C# 中的线程。第 5 部分。并行编程。

这是使用 PLINQ 的伪代码:

lines
  .AsParallel()
  .WithDegreeOfParallelism(YourNumberOfProcessors)
  .Select(e => ProcessYourData(e));
于 2012-11-29T12:36:05.643 回答