使用模态进度表单进行线程处理,无法更新标签的文本属性
我有一个 Windows 窗体,它是一个模态 mdi 子项,应该在正在进行一些紧张的后台工作时显示,因此用户在该工作完成之前无法使用任何控件。
非常简单,这是代码。
public partial class ProgressForm : Form
{
private int periodCount = 5;
public ProgressForm(String message)
{
InitializeComponent();
messageLabel.Text = message;
}
public void startThread()
{
Thread t = new Thread(new ThreadStart(doWork));
t.IsBackground = true;
t.Start();
}
void doWork()
{
while (true)
{
if (periodCount == 5)
{
periodCount = 1;
}
else
{
periodCount++;
}
switch (periodCount)
{
case 1: periodsLabel.Text = "."; break;
case 2: periodsLabel.Text = ". ."; break;
case 3: periodsLabel.Text = ". . ."; break;
case 4: periodsLabel.Text = ". . . ."; break;
case 5: periodsLabel.Text = ". . . . ."; break;
}
}
}
}
但是, periodLabel.Text 并没有像预期的那样改变!如何让它在后台执行其他操作的同时更新 UI?
ProgressForm progressForm = new ProgressForm("Your database data is being exported, please wait.");
progressForm.ShowDialog();
progressForm.startThread();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,以我的拙见,你不应该像现在这样扔掉一条线。
最佳实践是使用
BackgroundWorker
线程。其次,您的表单根本不是模态的,因为您仅使用
Show()
方法。为了使其成为模态表单,您需要使用ShowDialog()
方法。至于为什么您的表单会崩溃,从现在开始已经超出了我们的讨论范围。请考虑执行以下步骤:
BackgroundWorker
类;BackgroundWorker.DoWork()
方法为您完成脏活;BackgroundWorker.WorkerReportsProgress = true
;ReportProgress(int)
方法来ReportProgress()
。请参阅此问题(C#:使用填充 UI单独的线程。)和我的代码示例,我认为它简单地解释了BackgroundWorker类实例的使用。
注意:仍在寻找另一个示例。
编辑#1
这是一篇关于线程的好文章:C# 中的线程。
因为
乔恩·斯基特
这么说! .NET 中的多线程:简介和建议 。First, in my humble opinion, you should not just throw away a thread like you do.
The best practice is using a
BackgroundWorker
Thread.Second, you form isn't modal at all, as you only show it using the
Show()
method. In order to make it a modal form, you need to make it a dialog using theShowDialog()
method.As to why exactly your Form is crashing is quite out of scope from now on. Please consider following the following steps:
BackgroundWorker
class;BackgroundWorker.DoWork()
method do the dirty work for you;BackgroundWorker.WorkerReportsProgress = true
in the component model property window in design;ReportProgress()
using theReportProgress(int)
method.Please see this question (C#: Populating a UI using separate threads.) and my code sample which simply explains, I think, the use of a BackgroundWorker class instance.
Note: Still looking for another example.
EDIT #1
Here's a good article on threads: Threading in C#.
'Cause
Jon Skeet
said so! Multi-threading in .NET: Introduction and suggestions.您的应用程序很可能崩溃,因为您尝试直接从线程访问表单元素的属性(例如,当您调用PeriodsLabel.Text时),而不是使用线程中的BeginInvoke来调用表单上执行该属性的方法访问。
但使用 BackgroundWorker 类来处理此类事情会更好/更简单。
It's likely that your app is crashing because you are trying to access your form elements' properties directly from a thread (e.g. when you call PeriodsLabel.Text) rather than using BeginInvoke from your thread to call a method on your form which will do the property accessing.
But it's better/simpler to use the BackgroundWorker class for these kinds of things.