繁体   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