How can I refresh a label in Windows Forms from a background thread in C#?
本问题已经有最佳答案,请猛点这里访问。
我有一个线程与主窗体(UI)并行运行。它所做的(目前)就是每秒钟递增一个计数器。我想在Windows窗体中使用标签显示计数器的值。有可能吗?当我尝试以下代码时,我在showValue方法中得到一个编译错误。我必须声明ShowValue"static",以便从后台线程调用它。但是如果我这样做,我就不能使用"this."来访问showValue表单1中的标签。这是正确的方法吗?任何小费都将不胜感激,谢谢!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | private void count_secs() { while (!stopThread) { if (stopThread) { break; } num2++; // increment counter Form1.ShowValue(num2); // display the counter value in the main Form try { Thread.Sleep(1000); // wait 1 sec. } catch (ThreadInterruptedException) { if (stopThread) { break; } } } } |
然后在我的Form1课程中,我有:
1 2 3 4 5 6 | public static void ShowValue(int num) { this.label7.Text = num.ToString(); // compiler error here:"Keyword 'this' is not valid in a static method. } |
第一个问题是获取表单实例,如果调用表单上没有表单实例,则会导致application.openforms属性如下:
1 2 3 | Form1 frm = Application.OpenForms["Form1"] as Form1; if(frm != null) frm.ShowValue(num2); |
第二个问题是,您需要将方法修改为实例方法,并将其从跨线程异常中保存,修改方法如下:
1 2 3 4 5 6 7 8 9 10 11 | public void ShowValue(int num) { if (label7.InvokeRequired) { label7.BeginInvoke((MethodInvoker)delegate { label7.Text = num.ToString(); }); } else { label7.Text = num.ToString(); } } |
您不能从不同的线程随机访问GUI元素。对您的问题的简短回答是:使用现有结构。
- 如果你只是想经常做一些事情,那就用一个计时器。当时间到了,它将通知您的主线程(即"拥有"GUI),您可以在那里更新GUI元素。
- 如果您真的想创建自己的线程,请使用BackgroundWorker。它将提供线程安全事件,您可以从中更新GUI元素。
在静态方法
您的方法应该如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 | public void ShowValue(int num) { if(label7.InvokeREquired) { Action a = () => ShowValue(num); label7.Invoke(a); } else this.label7.Text = num.ToString(); } |
在此代码中,将对窗体的静态调用替换为实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | private void count_secs() { var frm = new Form1(); //create instance frm.Show(); // show form while (!stopThread) { if (stopThread) { break; } num2++; // increment counter //use form instance frm.ShowValue(num2); // display the counter value in the main Form try { Thread.Sleep(1000); // wait 1 sec. } catch (ThreadInterruptedException) { if (stopThread) { break; } } } |
编辑
您可能希望在方法
不一定要使
1 2 3 4 |
两个问题:
解决: