如何使用 for 循环的实时结果更新 GUI?
How can I update the GUI with live results from a for loop?
我在我的 c# 项目中使用 for 循环。
在某些情况下,我要迭代超过 500,000 个值 - GUI 直到循环结束才响应。
我可以让 GUI 在 for
循环内更新吗?
for (int i = 0; i < 100000; i++)
{
double s1 = rnd.NextDouble();
double s2 = rnd.NextDouble();
w = Math.Sqrt(-2 * Math.Log(s1)) * Math.Cos(2 * Math.PI * s2);
listBox1.Items.Add(w.ToString());
}
试试这个:
for (int i = 0; i < 100000; i++)
{
label.Text = i;
double s1 = rnd.NextDouble();
double s2 = rnd.NextDouble();
w = Math.Sqrt(-2 * Math.Log(s1)) * Math.Cos(2 * Math.PI * s2);
listBox1.Items.Add(w.ToString());
}
将 label.Text 替换为您的标签名称。
我做到这一点的最好方法是启动一个线程来用文本填充控件项,为此您需要从线程内部调用一个方法来填充列表框,这需要一个委托方法,
在您的 class、
中声明一个委托方法
delegate void SetListBoxDelg(string value);
然后启动一个线程来启动填充列表框的过程,
Thread t = new Thread(StartProc);
t.Start();
这是您调用填充列表框的方法的线程代码,
public void StartProc()
{
for (int i = 0; i < 100000; i++)
{
double s1 = rnd.NextDouble();
double s2 = rnd.NextDouble();
w = Math.Sqrt(-2 * Math.Log(s1)) * Math.Cos(2 * Math.PI * s2);
SetListBox(w.ToString());
}
}
这是从线程内部调用的方法,
private void SetListBox(string value)
{
if (this.InvokeRequired)
{
SetListBoxDelg dlg = new SetListBoxDelg(this.SetListBox);
this.Invoke(value);
return;
}
listBox1.Items.Add(value);
}
Jason Hughes 在上面回答了这个问题。使用显示计数器的控件的 Refresh():
for (int i = 0; i < 100000; i++)
{
labelIteration.Text = i.ToString();
labelIteration.Refresh();
double s1 = rnd.NextDouble();
double s2 = rnd.NextDouble();
w = Math.Sqrt(-2 * Math.Log(s1)) * Math.Cos(2 * Math.PI * s2);
}
如果它是单线程应用程序,您可能会冻结 GUI。尝试在循环中使用 Application.DoEvents() 方法。例如:
for (int i = 0; i < 100000; i++)
{
labelToShow.Text = i.ToString(); // live update of information on the GUI
labelToShow.Invalidate();
Application.DoEvents();
double s1 = rnd.NextDouble();
double s2 = rnd.NextDouble();
w = Math.Sqrt(-2 * Math.Log(s1)) * Math.Cos(2 * Math.PI * s2);
}
我在我的 c# 项目中使用 for 循环。
在某些情况下,我要迭代超过 500,000 个值 - GUI 直到循环结束才响应。
我可以让 GUI 在 for
循环内更新吗?
for (int i = 0; i < 100000; i++)
{
double s1 = rnd.NextDouble();
double s2 = rnd.NextDouble();
w = Math.Sqrt(-2 * Math.Log(s1)) * Math.Cos(2 * Math.PI * s2);
listBox1.Items.Add(w.ToString());
}
试试这个:
for (int i = 0; i < 100000; i++)
{
label.Text = i;
double s1 = rnd.NextDouble();
double s2 = rnd.NextDouble();
w = Math.Sqrt(-2 * Math.Log(s1)) * Math.Cos(2 * Math.PI * s2);
listBox1.Items.Add(w.ToString());
}
将 label.Text 替换为您的标签名称。
我做到这一点的最好方法是启动一个线程来用文本填充控件项,为此您需要从线程内部调用一个方法来填充列表框,这需要一个委托方法,
在您的 class、
中声明一个委托方法delegate void SetListBoxDelg(string value);
然后启动一个线程来启动填充列表框的过程,
Thread t = new Thread(StartProc);
t.Start();
这是您调用填充列表框的方法的线程代码,
public void StartProc()
{
for (int i = 0; i < 100000; i++)
{
double s1 = rnd.NextDouble();
double s2 = rnd.NextDouble();
w = Math.Sqrt(-2 * Math.Log(s1)) * Math.Cos(2 * Math.PI * s2);
SetListBox(w.ToString());
}
}
这是从线程内部调用的方法,
private void SetListBox(string value)
{
if (this.InvokeRequired)
{
SetListBoxDelg dlg = new SetListBoxDelg(this.SetListBox);
this.Invoke(value);
return;
}
listBox1.Items.Add(value);
}
Jason Hughes 在上面回答了这个问题。使用显示计数器的控件的 Refresh():
for (int i = 0; i < 100000; i++)
{
labelIteration.Text = i.ToString();
labelIteration.Refresh();
double s1 = rnd.NextDouble();
double s2 = rnd.NextDouble();
w = Math.Sqrt(-2 * Math.Log(s1)) * Math.Cos(2 * Math.PI * s2);
}
如果它是单线程应用程序,您可能会冻结 GUI。尝试在循环中使用 Application.DoEvents() 方法。例如:
for (int i = 0; i < 100000; i++)
{
labelToShow.Text = i.ToString(); // live update of information on the GUI
labelToShow.Invalidate();
Application.DoEvents();
double s1 = rnd.NextDouble();
double s2 = rnd.NextDouble();
w = Math.Sqrt(-2 * Math.Log(s1)) * Math.Cos(2 * Math.PI * s2);
}