为什么每个应用程序运行5秒钟没有响应,停止按钮无法单击?

问题描述 投票:1回答:3

我想用开始和停止按钮制作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;
}
c#
3个回答
2
投票

只需使用asyncawait模式来释放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回送应答消息)。


0
投票

我认为你的停止按钮不起作用因为你的:

loop= for (int i = 0; i < 100000 && !_stopLoop; ++i)

在这个循环中,_stopLoop变量始终是true,因为您使用的是!运算符。


0
投票

因为负责处理窗口消息(您的按钮单击)的执行线程正忙于执行您编写的代码。您的代码阻止(阻止)线程返回到保持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线程没有您的代码,它就会消耗消息并且您的应用程序再次活跃起来。

© www.soinside.com 2019 - 2024. All rights reserved.