2016-12-28 27 views
1

編輯:
我注意到這些滯後尖峯只發生在visual studio中調試時。如果我在Visual Stduio之外運行.exe,程序不會使用超過3%的CPU。任何人都可以告訴我爲什麼會發生這種情況?並行對於在2,3分鐘後導致大規模滯後峯值


我也遇到過使用的Parallel.For檢查大量代理(通過使webrequests)並行processing.I'm一個問題。這是我的函數:

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

+0

此外,這用於幾天前工作正常。現在我有這個問題沒有做任何改變的代碼.. – Catalin

+0

您或許可以使用探查器來檢查哪部分代碼持有CPU。事實上你沒有改變你的代碼中的任何東西,因爲它正常工作使我認爲HttpRequest調用之一的行爲可能與它前幾天的表現不同,很可能是因爲另一方的行爲有不同的表現(網站)。 –

+0

@o_weisman如何使用探查器?我使用了默認的診斷工具,以及導致大部分CPU使用率的原因,它說外部代碼。那是什麼意思? – Catalin

回答

2

正如承諾的異步/等待的例子,雖然看到你的更新,我不知道它是否會有所作爲。但由於它不適合評論裏面,貼在這裏;)

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方法可以使用實際的異步webcalls(我相信代碼以前包含在您的文章中),我相信處理可以真正改善。

+0

如果您使'CheckProxies'返回'async Task'而不是'async void',我會讓您滿意。 –

+0

@ScottChamberlain這就是我的理由;)更改簽名 –

+0

非常感謝您的幫助。在做了一些研究之後,似乎視覺工作室出現了滯後高峯,因爲一次拋出大量異常(但不是100%肯定)。 – Catalin

0

我不知道這是直接關係到你的問題,但MaxDegreeOfParallelism設置爲100並不好。你基本上是在告訴你的應用程序同時執行100個任務!根據MSDN

通常,您不需要修改此設置。但是,您可以選擇先進的使用場景,如這些明確設置:

  • 當你知道你正在使用一個特定的算法不會規模超過一定數目的核心。您可以設置屬性以避免在其他內核上浪費週期。

  • 當您同時運行多個算法並且想要手動定義每個算法可以使用多少系統時。您可以爲每個值設置一個P:System.Threading.Tasks.ParallelOptions.MaxDegreeOfParallelism值。

  • 當線程池的啓發式無法確定使用的線程的正確數量並可能最終注入太多的線程。例如,在長時間運行的循環體迭代中,線程池可能無法區分合理進度或活鎖或死鎖,並且可能無法回收爲提高性能而添加的線程。在這種情況下,您可以設置屬性以確保您不會使用超過合理數量的線程。

我會嘗試刪除該值,看看你的應用程序的行爲!