我想用开始和停止按钮制作Pinger,我从这个论坛得到的代码就像stopLoop:
private bool _stopLoop;
private void button1_Click(object sender, EventArgs e)
{
_stopLoop = false;
for (int i = 0; i < 100000 && !_stopLoop; ++i)
{
using (Ping p = new Ping())
{
lbPing.Text = p.Send(tbUrl.Text).RoundtripTime.ToString() + "ms\n";
lbPing.Update();
}
}
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case 0x84:
base.WndProc(ref m);
if ((int)m.Result == 0x1)
m.Result = (IntPtr)0x2;
return;
}
base.WndProc(ref m);
}
private void btStop_Click(object sender, EventArgs e)
{
_stopLoop = true;
}
只需使用async
和await
模式来释放UI
private async void button1_Click(object sender, EventArgs e)
{
_stopLoop = false;
while( !_stopLoop)
{
using (var p = new Ping())
{
var pingReply = await p.SendPingAsync(IPAddress.Parse("1.1.1.1"), 10000);
lbPing.Text = $"{pingReply.RoundtripTime} ms";
await Task.Delay(1000);
}
}
}
其他资源
SendPingAsync(IPAddress, Int32)
将具有指定数据缓冲区的Internet控制消息协议(ICMP)echo消息发送到具有指定IPAddress的计算机,并从该计算机接收相应的ICMP echo reply消息作为异步操作。此重载允许您指定操作的超时值。
参数
IPAddress
标识作为ICMP回送消息目标的计算机的IP地址。
Int32
发送回显消息之后的最大毫秒数(等待ICMP回送应答消息)。
我认为你的停止按钮不起作用因为你的:
loop= for (int i = 0; i < 100000 && !_stopLoop; ++i)
在这个循环中,_stopLoop
变量始终是true
,因为您使用的是!
运算符。
因为负责处理窗口消息(您的按钮单击)的执行线程正忙于执行您编写的代码。您的代码阻止(阻止)线程返回到保持UI响应交互的正常工作。在编写Windows应用程序时,我们必须考虑这一点,而不是阻止(保持忙碌)在按钮单击处理程序中开始执行代码的线程。简单来说,您必须让进入点击处理程序的线程尽快退出。在你的情况下,你已经把它发送到一个方法,当你需要做的是用它开始单独执行长时间运行的方法,然后让它返回时,它不会回到你的代码5秒钟处理UI更新
我们通过异步运行工作代码或使用将为其创建[类似]单独线程的机制来实现此目的
使用async:https://docs.microsoft.com/en-us/windows/uwp/debug-test-perf/keep-the-ui-thread-responsive
使用backgroundworker:How to use a BackgroundWorker?
(我故意避免链接任何鼓励你直接创建和管理自己的线程的东西。以上两种机制更适合现代应用程序)
作为辅助信息,窗口基本上由具有消息队列的应用程序(先进先出)起作用。您所做的一切(移动鼠标,单击,按键)都会被发布到此队列中,并且您的程序有一个线程可以处理事件并对其进行操作。如果你让这个线程在几秒钟内忙着做你的代码,它就不会消耗消息。操作系统注意到队列越来越长,并且在标题中淡化窗口/放置“无响应”。只要ui线程没有您的代码,它就会消耗消息并且您的应用程序再次活跃起来。