使用 Ping 映射活动 IP 的线程问题 - C#

发布于 2024-08-18 05:26:47 字数 1211 浏览 4 评论 0原文

我正在尝试创建一个简单的网络工具来 ping 本地子网上所有可能的 IP,并在 DataGridView 中提供此类 IP 的列表。我刚开始不得不考虑线程,这对于一个崭露头角的程序员来说是一件好事。抱歉,但您可能需要向我解释一下,但在我看来这应该可行。在我尝试将其放入后台工作线程之前,应用程序只会挂起并给我一个“无响应”。

提前致谢。

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

            }


    }

I am trying to create a simple Network Tool to ping all possible IPs on your local subnet and provide a list of such IPs in a DataGridView. I am new to having to consider threading which is a good thing to come across as a budding programmer. Sorry, but you are probably going to have to do some explaining to me, but in my mind this should work. Before I tried putting it in a backgroundworker thread, the application would just hang and give me a "Not Responding".

thanks ahead of time.

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

            }


    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

丘比特射中我 2024-08-25 05:26:47

您无法从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;
}

You cannot access directly the progressBar1 (or any other UI element) from the backgroundWorker1 "DoWork" event, you have to use the backgroundWorker1.ProgressChanged method and handle ProgressChanged event:

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

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

WorkerReportsProgress should be assigned to true
and the event of ProgressChanged to the following method

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // assuming the Minimum = 0 and Maximum = 100 on progressBar
    progressBar.Value = e.ProgressPercentage;
}
猛虎独行 2024-08-25 05:26:47

部分问题在于您直接从后台线程访问 UI 元素。 progressBar 字段大概是一个 UI 进度条控件,只能从 UI 线程安全地访问。您必须使用对 .Invoke 的调用来从 UI 线程设置此值。

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

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

Part of the problem is that you are directly accessing a UI element from your background thread. The field progressBar is presumably a UI progress bar control and can only be safely accessed from the UI thread. You must use a call to .Invoke to set this value from the UI thread.

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

private void UpdateProgressBarByOne() {
  progressBar.Value += 1;  
}
时光倒影 2024-08-25 05:26:47

啊,我喜欢穿线。它使程序变得更加有趣......

所以当我开始学习如何制作响应式应用程序时,我遇到了这个函数:Application.DoEvents()

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

它的作用是使您的表单处理它接收到的一些窗口事件。我认为你的代码可以更改为在每个 ping 请求后包含一个调用...

即在 on click 事件处理程序中

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

现在这又回到了 dot net 时代,并且一直保留到现在,但是,这不是你应该掉以轻心的事情。如果您单击表单上的另一个按钮,它将启动另一个尝试执行的线程,如果您不小心,则会导致表单上的线程异常。一些开发人员会告诉您不要使用此方法,但自从您开始以来,我会说尝试一下:)

根据应用程序,我可能不会使用此方法。相反,我实际上要做的是创建多个处理“列车”;系统拥有的每个 CPU 核心都有一个。我将要扫描的 ip 添加到队列对象中,然后启动 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 来创建一个系统,该系统使用其他计算机的多核来完成诸如图像处理之类的工作(或使用 pa....... ;)

Ah I love threading. It makes programs so much more interesting...

So as I started off learning about how to make responsive applications I came across the function: Application.DoEvents()

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

What this does is causes your form to process some of the window events it's receiving. I think that your code could change to include a call after each ping request...

i.e. within the on click event handler

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

Now this was back in the pre dot net days and it's survived till now however, it's not something that you should take lightly. If you click another button on the form it will start off another thread that will attempt to execute and if you're not careful cause thread exceptions on your form. Some developers will tell you don't use this but since your starting off I'd say give it a shot :)

I might not use this method depending on the application. Instead what I would do it actually do is to create several processing "trains"; one for each cpu core that the system had. I'd add the ips to be scanned to a queue object and then I would start up 2 to 4 instances of threads (http://msdn.microsoft.com/en-us/library/system.threading.thread.aspx) each of which taking an item off the queue in turn, process the information (i.e. do the ping logic) and put the result on another queue; and output queue. Every time a train would finish an item for work it would raise an event at the other end of which there would be a handler in the form. Using the Invoke to make thread safe calls (http://msdn.microsoft.com/en-us/library/ms171728.aspx) on my form I would update the UI's information accordingly.

Threading is fun dude :) over time you can find that you can use MSMQ to make a system that uses the multicores of other computers to do jobs such as image processing (or something with pa....... ;)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文