简体   繁体   English

部分代码不会立即执行

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

My app detect is ip changed or not. 我的应用程序检测到IP是否更改。 If ip is different than previous it saves new ip to file. 如果ip与以前的IP不同,则将新的ip保存到文件中。 Seems pretty easy. 似乎很容易。

Delay function: 延时功能:

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

Button click event: 按钮点击事件:

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;

    }
 }

The thing is if I left the code like this the part: pictureBox1.BackColor = Color.Green; 关键是,如果我将这样的代码保留为这一部分: pictureBox1.BackColor = Color.Green; is not going to execute. 将不会执行。

I have to change from this: 我必须对此进行更改:

pictureBox1.BackColor = Color.Green;

To this: 对此:

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

And now picturebox colour is changing. 现在,Picturebox的颜色正在改变。 Why does that Delay repair that? 为什么那延迟修复? If I put MessageBox insted of Picturebox, problem does not even exist. 如果我将MessageBox插入Picturebox,甚至不存在问题。 It work as a charm without MyDelay too. 如果没有MyDelay,它也可以作为一种魅力。 So what is the point? 那有什么意义呢?

Another question: it should check the ip every 1 second. 另一个问题:应该每1秒检查一次ip。 So why when I change the ip I have to wait about 5 second for change detection? 那么,为什么更改IP时我必须等待5秒钟才能进行更改检测? It should save new ip after 1 second when connection appears, but it takes about 5 second to recognize change 连接出现后,它应该在1秒钟后保存新的IP,但是大约需要5秒钟才能识别更改

You are doing all your work in the main thread. 您正在主线程中完成所有工作。 Also the UI is being updated in the main thread. UI也在主线程中被更新。 This means that you're not allowing the UI to update itself in any way. 这意味着您不允许用户界面以任何方式进行更新。

When you call your delay function it calls Application.DoEvents() which lets the UI to update itself. 当您调用延迟函数时,它会调用Application.DoEvents() ,以使UI自行更新。

You should refactor the code to use a timer, asynchronous methods or a background worker thread so that the UI can stay responsive. 您应该重构代码以使用计时器,异步方法或后台工作线程,以便UI可以保持响应状态。

You should never create an endless while (true) in a button click which blocks the gui for updating. 您绝对不要在按钮单击中创建无休止的while (true) ,这会阻止gui进行更新。 Thats why your PictureBox isn't repainted (but the code is executed). 这就是为什么您的PictureBox不会重新绘制(但是代码已执行)的原因。 If you place your sleep there (containing Application.DoEvents() ) , the paint messages are handled and your PictureBox is repainted. 如果您在那里睡觉(包含Application.DoEvents() ,则会处理绘制消息,并重新绘制PictureBox But still the GUI thread is blocked. 但是,GUI线程仍然被阻止。

Using the Application.DoEvents() this way is bad practice , because other buttons/formcloses are also handled here which makes your application very unstable. 这种方式使用Application.DoEvents()不好的做法 ,因为在此还会处理其他按钮/窗体关闭,这会使您的应用程序非常不稳定。 So get rid of the Application.DoEvents().. 因此,摆脱Application.DoEvents()。

Use a Timer instead to check the site for your external IP! 请改用Timer检查该站点的外部IP!


Something like: PSEUDO 类似于: 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;
}

inside a snipped .net cannot update the interface, you can use Application.DoEvents() to solve the problem. 在一个已删除的.net内部无法更新接口时,可以使用Application.DoEvents()解决此问题。 Maybe this question can help further. 也许这个问题可以进一步帮助。

If I understood your intentions correctly, you can try async await (not sure why it requires a while loop and try catch to get the result of the url though): 如果我正确理解了您的意图,则可以尝试异步等待(不知道为什么它需要一个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