2010-01-20 11 views
1

我正在嘗試創建一個簡單的網絡工具來ping所有可能的IP在您的本地子網上,並在DataGridView中提供這樣的IP的列表。我不得不考慮線程,這對於作爲新手程序員來說是件好事。對不起,你可能不得不向我做一些解釋,但在我看來這應該起作用。在我嘗試將它放入後臺工作線程之前,應用程序會掛起並給我一個「不響應」。使用Ping映射活動IP的線程問題 - C#

提前致謝。

 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     count = 0; 
     for (int j = 1; j < 255; j++) 
      for (int i = 1; i < 255; i++) 
      { 
       Ping ping = new Ping(); 
       PingReply pingreply = ping.Send(IPAddress.Parse(locip[0] + "." + locip[1] + "." + j + "." + i)); 

       if (pingreply.Status == IPStatus.Success) 
       { 
        status = "o"; 
        repAddress = pingreply.Address.ToString(); ; 
        repRoundtrip = pingreply.RoundtripTime.ToString(); 
        repTTL = pingreply.Options.Ttl.ToString(); 
        repBuffer = pingreply.Buffer.Length.ToString(); 

        string[] lineBuffer = { status, repAddress, repRoundtrip, repTTL, repBuffer }; 
        ipList.Rows.Add(lineBuffer); 
        count += 1; 
        progressBar.Value += 1; 
       } 

      } 


    } 
+0

所以這是或不是在BackgroundWorker?你能告訴我們你的線程設置代碼嗎? – cmw 2010-01-20 23:08:31

+0

在設計視圖中,我添加了名爲backgroundWorker1的BackgroundWorker對象,並在button1的單擊事件上調用了 backgroundWorker1.RunWorkerAsync(); 但我再次相信問題在於ping程序和循環。在我添加BackgroundWorker之前,當這個確切的代碼出現在點擊事件中時,它會掛起並凍結(「未響應」)。 P.S.使用Visual Studio 2008 – user48202 2010-01-20 23:35:28

+1

嗯,你正在做65536坪。其中許多人都沒有迴應。您應該將其本地化爲最終的子網。這樣做太過於有意義的方式處理。 – 2010-01-21 00:05:57

回答

1

部分問題是您直接從後臺線程訪問UI元素。字段progressBar大概是一個UI進度條控件,只能從UI線程安全地訪問。您必須使用.Invoke調用來從UI線程設置此值。

progressBar.Invoke(new MethodInvoker(UpdateProgressBarbyOne)); 
... 

private void UpdateProgressBarByOne() { 
    progressBar.Value += 1; 
} 
+0

感謝您提供progressBar的提示,但是您能否詳細瞭解如何實現這一目標? (什麼?)。調用 – user48202 2010-01-20 23:38:58

+0

@jon,確實如此。更新了我的答案 – JaredPar 2010-01-20 23:42:26

2

不能從backgroundWorker1 「DoWork的」 事件直接訪問progressBar1(或任何其他UI元素),您必須使用backgroundWorker1.ProgressChanged方法和處理ProgressChanged事件:

// instead of progressBar.Value += 1 
// use the following 

const int total = 254 * 254; 
backgroundWorker1.ReportProgress(count/total); 

WorkerReportsProgress應分配給真正 和ProgressChanged的以下方法

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    // assuming the Minimum = 0 and Maximum = 100 on progressBar 
    progressBar.Value = e.ProgressPercentage; 
} 
0

啊我喜歡穿的事件。它使節目這麼多有意思......

所以當我開始學習如何做出響應的應用程序,我碰到的功能:Application.DoEvents()

(http://msdn.microsoft.com/en-us/library/system.windows.forms.application.doevents.aspx)

這樣做是什麼導致您的表單處理它正在接收的一些窗口事件。我認爲,你的代碼可能會改變,包括每個查詢請求後,呼叫...

上單擊事件處理

count = 0; 
     for (int j = 1; j < 255; j++) 
      for (int i = 1; i < 255; i++) 
      { 
       Ping ping = new Ping(); 
       PingReply pingreply = ping.Send(IPAddress.Parse(locip[0] + "." + locip[1] + "." + j + "." + i)); 

       if (pingreply.Status == IPStatus.Success) 
       { 
        status = "o"; 
        repAddress = pingreply.Address.ToString(); ; 
        repRoundtrip = pingreply.RoundtripTime.ToString(); 
        repTTL = pingreply.Options.Ttl.ToString(); 
        repBuffer = pingreply.Buffer.Length.ToString(); 

        string[] lineBuffer = { status, repAddress, repRoundtrip, repTTL, repBuffer }; 
        ipList.Rows.Add(lineBuffer); 
        count += 1; 
        progressBar.Value += 1; 
       } 
       Application.DoEvents(); //but not too often. 
      } 

內,即現在,這又回到了前點網天,它的存活至但現在,這不是你應該輕視的東西。如果您單擊表單上的另一個按鈕,它將從另一個將嘗試執行的線程開始,如果您不小心在表單上導致線程異常。一些開發人員會告訴你不要使用這個,但自從你開始的時候,我會說給它一個鏡頭:)

我可能不會使用此方法取決於應用程序。實際上,我要做的是創建幾個處理「火車」;一個用於系統所具有的每個CPU核心。我會添加ips來掃描隊列對象,然後我會啓動2到4個線程實例(http://msdn.microsoft.com/en-us/library/system.threading.thread.aspx),每個線程依次從隊列中取出一個項目,處理信息(即執行ping邏輯)並將結果放在另一個隊列中;並輸出隊列。每次火車完成一項工作時,它會在另一端引發一個事件,在該事件的後面會有一個處理程序。使用Invoke在我的表單上進行線程安全調用(http://msdn.microsoft.com/en-us/library/ms171728.aspx),我會相應地更新UI的信息。

線程是一個有趣的傢伙:)隨着時間的推移,你會發現你可以使用MSMQ來製作一個使用其他計算機的多核來完成諸如圖像處理等工作的系統。;)