簡體   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