簡體   English   中英

使用Ping映射活動IP的線程問題-C#

[英]Threading issues using Ping to map active IPs - C#

我正在嘗試創建一個簡單的網絡工具來ping您本地子網上的所有可能的IP,並在DataGridView中提供此類IP的列表。 我是新來的必須考慮線程處理的人,這是一個嶄露頭角的程序員的好東西。 抱歉,您可能需要向我做一些解釋,但是在我看來,這應該可以工作。 在嘗試將其放入backgroundworker線程之前,該應用程序將掛起並給我“無響應”。

提前謝謝。

        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;
                }

            }


    }

您無法從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分配為true,並將ProgressChanged事件更改為以下方法

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

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

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

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

啊,我喜歡穿線。 它使程序變得更加有趣...

因此,當我開始學習如何制作響應式應用程序時,我遇到了以下函數:Application.DoEvents()

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

這樣做是使您的表單處理正在接收的某些窗口事件。 我認為您的代碼可能會更改為在每個ping請求之后都包含一個調用...

即在點擊事件處理程序中

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/zh-cn/library/system.threading.thread.aspx )每一個依次將一個項目從隊列中取出,處理信息(即執行ping邏輯)並將結果放在另一個隊列中; 和輸出隊列。 每次火車要完成一項工作時,都會在另一端引發一個事件,該事件的形式是處理程序。 使用窗體上的Invoke進行線程安全調用( http://msdn.microsoft.com/zh-cn/library/ms171728.aspx ),我將相應地更新UI信息。

線程很有趣:)隨着時間的流逝,您會發現可以使用MSMQ來創建一個使用其他計算機的多核來完成諸如圖像處理(或帶有pa .......;之類的工作)的系統。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM