我的应用检测是否已更改。如果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);
现在图片框的颜色正在发生变化。为什么延迟修复呢?如果我把MessageBox放在Picturebox中,问题就不存在了。它也可以作为没有MyDelay的魅力。那有什么意义呢?
另一个问题:它应该每1秒检查一次ip。那么为什么当我改变ip时我必须等待大约5秒才能进行变化检测?它应该在连接出现后1秒后保存新的ip,但识别更改需要大约5秒
答案 0 :(得分:1)
您正在主线程中完成所有工作。 UI也在主线程中更新。这意味着您不允许UI以任何方式更新自身。
当您调用延迟函数时,它会调用Application.DoEvents()
,让UI自行更新。
您应该重构代码以使用计时器,异步方法或后台工作线程,以便UI可以保持响应。
答案 1 :(得分:1)
你不应该在按钮点击中创建一个无限的while (true)
,它会阻止gui进行更新。这就是为什么你的PictureBox
没有重新绘制(但代码被执行)的原因。如果您将睡眠放在(包含Application.DoEvents()
),则会处理绘制消息并重新绘制PictureBox
。但是仍然阻止了GUI线程。
以这种方式使用Application.DoEvents()
是不良做法,因为此处还处理了其他按钮/ formcloses,这会使您的应用程序非常不稳定。 所以摆脱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;
}
答案 2 :(得分:0)
在剪切的.net内部无法更新界面,您可以使用Application.DoEvents()
来解决问题。也许this question会有所帮助。
答案 3 :(得分:0)
如果我理解你的意图,你可以尝试异步等待(不知道为什么它需要一个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");
}
}