【发布时间】:2021-01-25 05:20:58
【问题描述】:
我目前有一个 ping IP 列表的应用程序。 用户单击一个按钮,它会持续 ping 所有 IPS 20 秒。 我想要做的是单击一个按钮来停止它。
我创建了一个名为“Process”的函数,它会在单击按钮时调用此进程。
我试图创建一个 bool 值和 while 循环,当它为 false 并让停止按钮将 bool 值更改为 true,但它似乎并没有停止任何事情,事实上我什至无法关闭窗口,直到ping 已完成。
我的代码如下。
private bool _stopLoop;
private void btnPlay_Click(object sender, EventArgs e)
{
Process();
}
private void Process()
{
while (_stopLoop == false)
{
for (int i = 0; i < 20; i++)
{
foreach (DataGridViewRow dataGridView1Row in dataGridView1.Rows)
{
var count = 20;
progressBar1.Value = i * progressBar1.Maximum / count;
Application.DoEvents();
var url = dataGridView1Row.Cells[1].Value.ToString();
int timeout = 500;
Ping ping = new Ping();
PingReply pingreply = ping.Send(url, timeout);
PingReply result = null;
IPStatus status;
result = pingreply;
status = result.Status;
if (status != IPStatus.Success)
{
dataGridView1Row.Cells[0].Style.BackColor = Color.Red;
dataGridView1Row.Cells[0].Value = "Offline";
}
else
{
dataGridView1Row.Cells[0].Style.BackColor = Color.Green;
dataGridView1Row.Cells[0].Value = "Online";
}
}
}
}
}
private void btnStop_Click(object sender, EventArgs e)
{
_stopLoop = true;
}
【问题讨论】:
-
您需要将 ping 逻辑与用户界面分开。您可以查看 Threading 或更简单的 BackgroundWorker 组件
-
您的循环没有给第二个按钮机会。要为时间跨度做事,请使用计时器!
-
async/await的主要用例。 -
这里有很多不好的做法,但最重要的是使用
DoEvents和在 UI 线程上使用高延迟同步操作。正如 Alejandro 所暗示的那样,您会做得更好,完全删除DoEvents从而避免重新进入,并将阻塞操作更改为异步操作。让编译器处理异步工作流的编排;避免这样的代码是我们首先发明异步工作流的原因。