我正在使用Windows窗体应用程序处理一个小型实验项目,单击按钮后,while循环出现问题。单击button2后,应将布尔值 var1 var2 var3 var4 var5 var6
var1 -1 0 0 0 0 0
var2 0 -1 0 0 0 0
var3 0 0 -1 0 0 0
var4 0 0 0 -1 0 0
var5 0 0 0 0 -1 0
更改为false,并且循环应停止,但不是。
b
答案 0 :(得分:3)
您的代码可以使用,但是有点不完整; Button2中的事件有时会丢失或延迟,这可能是由于您将对Sleep()
和DoEvents
的调用混合在一起的原因,因此强烈建议不要使用DoEvents,并会因引入async
而废止和await
。另外,您一次只能初始化Random
(除非您做的事情确实很奇怪)。
如果使点击处理程序异步,则可以得到更好,更现代的解决方案,例如:
private volatile Boolean b;
private async void button1_Click(object sender, EventArgs e)
{
Random rnd = new Random();
b = true;
while (b)
{
int r = rnd.Next(0, 254);
int n = rnd.Next(0, 254);
int d = rnd.Next(0, 254);
this.BackColor = Color.FromArgb(r, n, d);
await Task.Delay(200);
}
}
private void button2_Click(object sender, EventArgs e)
{
b = false;
}
}
但是,此解决方案也有其问题。想象一下,例如,如果单击两次Button1会发生什么。可能不是预期的。
我建议您将更改颜色的逻辑更改为timer control,并使用Button1
事件处理程序启用它,并使用Button2
事件处理程序禁用它。
public Form1()
{
InitializeComponent();
this.timer1.Interval = 200;
}
private Random rnd = new Random();
private void button1_Click(object sender, EventArgs e)
{
this.timer1.Enabled = true;
}
private void button2_Click(object sender, EventArgs e)
{
this.timer1.Enabled = false;
}
private void timer1_Tick(object sender, EventArgs e)
{
int r = rnd.Next(0, 254);
int n = rnd.Next(0, 254);
int d = rnd.Next(0, 254);
this.BackColor = Color.FromArgb(r, n, d);
}
不是那么简单吗?
答案 1 :(得分:0)
在您的代码中,您正在UI线程上调用 Thread.Sleep 方法。这将导致UI阻塞。您可以通过扩展 Thread.Sleep 中的毫秒值来检查它。
要使UI响应,请使用hack Application.DoEvents()。它将停止所有其他线程并调用所有正在等待的方法(在此示例中,该方法被循环阻止)。在运行该应用程序后,如果没有它,您的表单将被冻结,并且您将无法单击按钮或移动窗口。
这不是编写代码的正确方法。应用程序应该在后台执行最耗时的工作,并且只能切换较短的时间以在UI上执行操作。
好的方法是在后台循环时开始,在后台计算颜色,并在需要时使用委托切换到UI。
delegate void ChangeColorDelegate(Color c);
public partial class Form1 : Form
{
Thread thread;
Boolean b;
Random Random;
public Form1()
{
InitializeComponent();
thread = new Thread(ChangeColorBackground);
thread.Start();
Random = new Random();
}
private void button1_Click(object sender, EventArgs e)
{
b = true;
}
private void button2_Click(object sender, EventArgs e)
{
b = false;
}
private void ChangeColorBackground()
{
while (true)
{
if (b == true)
{
int r = Random.Next(0, 254);
int n = Random.Next(0, 254);
int d = Random.Next(0, 254);
Color c = Color.FromArgb(r, n, d);
ChangeColorThreadSafe(c);
}
System.Threading.Thread.Sleep(100);
}
}
private void ChangeColorThreadSafe(Color c)
{
if (button1.InvokeRequired)
{
ChangeColorDelegate delgate = new ChangeColorDelegate(ChangeColorThreadSafe);
button1.Invoke(delgate, new object[] { c });
}
else
{
this.BackColor = c;
}
}
}
我在github上创建了示例。