平行于2,3分钟后引起大量滞后尖峰

时间:2016-12-28 06:17:48

标签: c# multithreading cpu-usage webrequest parallel.for

修改
 我注意到这些滞后峰值只发生在visual studio中调试时。如果我在Visual Stduio之外运行.exe,程序不会使用超过3%的CPU。任何人都可以告诉我为什么会这样?


我遇到了并行处理的问题。我使用Parallel.For来检查大量代理(通过制作webrequests)。这是我的功能:

private ConcurrentBag<string> TotalProxies = new ConcurrentBag<string>();
private void CheckProxies()
{
    ParallelOptions pOptions = new ParallelOptions();
    pOptions.MaxDegreeOfParallelism = 100;
    int max = TotalProxies.Count;
    Invoke(new Action(() => { lbl_Status.Text = "Checking"; }));
    Parallel.For(0, max, pOptions, (index, loopstate) =>
    {
        string Proxy = TotalProxies.ElementAt(index);
        if (WebEngine.IsProxyWorking(Proxy))
        {
            WorkingProxies.Add(Proxy);
            workingp++;
            Invoke(new Action(() =>
            {
                lstv_Working.Items.Add(Proxy);
                lbl_Working.Text = workingp.ToString();
            }));
        }
        checkedp++;
        Invoke(new Action(() => { lbl_Checked.Text = checkedp.ToString(); }));

        if (Stop)
            loopstate.Stop();
    });
    Invoke(new Action(() => {
        lbl_Status.Text = "Idle";
    }));
}

我的问题如下:
该程序适用于前0-2000个请求,其中cpu使用率约为3-5%。然后,在2-3分钟后,我遇到了大量频繁的滞后峰值,导致CPU使用率跃升至100% 。我不知道为什么会这样,因为它一直运作到现在。我希望有人能帮助我理解是什么导致了这一点 在这里,您可以看到我的问题:Lag spikes here

2 个答案:

答案 0 :(得分:2)

正如承诺的async / await的一个例子,虽然看到你的更新,但我不确定它是否会有所作为。但由于它不符合评论内容,因此将其发布在此处;)

private ConcurrentBag<string> TotalProxies = new ConcurrentBag<string>();
private async Task CheckProxies()
{
    lbl_Status.Text = "Checking"; //NB, invoking is omitted assuming that CheckProxies is called from the UI thread itself
    var tasks = TotalProxies.Select(CheckProxy);
    await Task.WhenAll(tasks);
    lbl_Status.Text = "Idle";
}

private async Task<bool> CheckProxy(string p)
{   
    bool working = await Task.Run(() => WebEngine.IsProxyWorking(p)); //would be better if IsProxyWorking itself uses async methods and returns a task, so Task.Run isn't needed. Don't know if it's possible to alter that function?
    if(working)
    {
        WorkingProxies.Add(p);
        workingp++; //Interlocked.Increment is not necessary because after the await we're back in the main thread
        lstv_Working.Items.Add(p);  //are these items cleared on a new run? 
        lbl_Working.Text = workingp.ToString();
    }
    checkedp++;
    lbl_Checked.Text = checkedp.ToString(); 
    return working;
}

注意,由于我无法测试实际代码,因此我不确定效率。您当前的代码可能表现更好。但是如果IsProxyWorking方法可以使用实际的异步网络连接(我相信代码以前包含在你的帖子中),我相信处理可以真正改善。

答案 1 :(得分:0)

我不知道这是否与您的问题直接相关,但将MaxDegreeOfParallelism设置为100并不好。您基本上是在告诉您的应用程序同时执行100项任务!根据{{​​3}}

  

通常,您无需修改​​此设置。但是,您可以选择在高级使用方案中明确设置它,例如:

     
      
  • 当您知道您正在使用的特定算法不会超出一定数量的核心时。您可以设置该属性以避免在其他核心上浪费周期。

  •   
  • 当您同时运行多个算法并希望手动定义每个算法可以使用多少系统时。您可以为每个设置P:System.Threading.Tasks.ParallelOptions.MaxDegreeOfParallelism值。

  •   
  • 当线程池的启发式方法无法确定要使用的正确线程数时,最终可能会注入太多线程。例如,在长时间运行的循环体迭代中,线程池可能无法区分合理进度或活锁或死锁,并且可能无法回收为提高性能而添加的线程。在这种情况下,您可以设置属性以确保您不会使用超过合理数量的线程。

  •   

我会尝试删除此值并查看您的应用程序的行为!