繁体   English   中英

部分代码不会立即执行

[英]Part of code doesn't execute without delay

我的应用程序检测到IP是否更改。 如果ip与以前的IP不同,则将新的ip保存到文件中。 似乎很容易。

延时功能:

public void MyDelay(int milliseconds)
{
    Stopwatch stopwatch = Stopwatch.StartNew();
    while (stopwatch.ElapsedMilliseconds <= (long)milliseconds)
    {
        Application.DoEvents();
    }
}

按钮点击事件:

private void button1_Click(object sender, EventArgs e)
  {
    pictureBox1.BackColor = Color.Green;

    while (true)
    {
        while (true)    //force obtain new_ip
        {

            try

            {
                new_ip = new System.Net.WebClient().DownloadString("https://api.ipify.org");

            }

            catch
            {
                MyDelay(1000);
                continue;

            }
            break;


        }


        if (old_ip != new_ip)
        {
            pictureBox1.BackColor = Color.Red;
            File.AppendAllText(@"C:\users\pc\Desktop\ip.txt", new_ip + "\r\n");
            old_ip = new_ip;
            MessageBox.Show("New ip saved");
        }
        pictureBox1.BackColor = Color.Green;

    }
 }

关键是,如果我将这样的代码保留为这一部分: pictureBox1.BackColor = Color.Green; 将不会执行。

我必须对此进行更改:

pictureBox1.BackColor = Color.Green;

对此:

pictureBox1.BackColor = Color.Green;
MyDelay(1);

现在,Picturebox的颜色正在改变。 为什么那延迟修复? 如果我将MessageBox插入Picturebox,甚至不存在问题。 如果没有MyDelay,它也可以作为一种魅力。 那有什么意义呢?

另一个问题:应该每1秒检查一次ip。 那么,为什么更改IP时我必须等待5秒钟才能进行更改检测? 连接出现后,它应该在1秒钟后保存新的IP,但是大约需要5秒钟才能识别更改

您正在主线程中完成所有工作。 UI也在主线程中被更新。 这意味着您不允许用户界面以任何方式进行更新。

当您调用延迟函数时,它会调用Application.DoEvents() ,以使UI自行更新。

您应该重构代码以使用计时器,异步方法或后台工作线程,以便UI可以保持响应状态。

您绝对不要在按钮单击中创建无休止的while (true) ,这会阻止gui进行更新。 这就是为什么您的PictureBox不会重新绘制(但是代码已执行)的原因。 如果您在那里睡觉(包含Application.DoEvents() ,则会处理绘制消息,并重新绘制PictureBox 但是,GUI线程仍然被阻止。

这种方式使用Application.DoEvents()不好的做法 ,因为在此还会处理其他按钮/窗体关闭,这会使您的应用程序非常不稳定。 因此,摆脱Application.DoEvents()。

请改用Timer检查该站点的外部IP!


类似于: PSEUDO

public class Form1: Form
{
    private Timer _timer;

    public Form1()
    {
        InitializeComponent();
        _timer = new Timer(.....);
        _timer.Tick += Timer_Tick;
        // etc!!!
    }

}

private void Timer_Tick(object sender, EventArgs e)
{
    string new_ip;
    try
    {
        new_ip = new System.Net.WebClient().DownloadString("https://api.ipify.org");

    }
    catch 
    { 
        return;
    }

    if (old_ip != new_ip)
    {
        pictureBox1.BackColor = Color.Red;
        File.AppendAllText(@"C:\users\pc\Desktop\ip.txt", new_ip + "\r\n");
        old_ip = new_ip;
        MessageBox.Show("New ip saved");
    }
    else
        pictureBox1.BackColor = Color.Green;
}

在一个已删除的.net内部无法更新接口时,可以使用Application.DoEvents()解决此问题。 也许这个问题可以进一步帮助。

如果我正确理解了您的意图,则可以尝试异步等待(不知道为什么它需要一个while循环,然后尝试catch以获取url的结果):

    private async void button1_Click(object sender, EventArgs e)
    {
        pictureBox1.BackColor = Color.Green;

        var newIp = await GetIpAsync();

        if (oldIp != newIp)
            pictureBox1.BackColor = Color.Red;
    }

    private async Task<string> GetIpAsync()
    {
        using (var httpClient = new HttpClient())
        {
            return await httpClient.GetStringAsync(@"https://api.ipify.org");
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM