使用模态进度表单进行线程处理,无法更新标签的文本属性

发布于 2024-10-08 09:09:54 字数 1321 浏览 5 评论 0 原文

我有一个 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();

I have a Windows Form, which is a modal mdi child, that is suppose to be shown when some intense background work is going on, so the user cannot use any of the controls until that work is finished.

It is very simple, here is the code.

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;
            }
        }
    }
}

but, the periodsLabel.Text does not change as it is suppose to! How do I get it to update the UI while doing something else in the background?

ProgressForm progressForm = new ProgressForm("Your database data is being exported, please wait.");
progressForm.ShowDialog();
progressForm.startThread();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

远昼 2024-10-15 09:09:54

首先,以我的拙见,你不应该像现在这样扔掉一条线。

最佳实践是使用 BackgroundWorker 线程。

其次,您的表单根本不是模态的,因为您仅使用 Show() 方法。为了使其成为模态表单,您需要使用 ShowDialog() 方法。

至于为什么您的表单会崩溃,从现在开始已经超出了我们的讨论范围。请考虑执行以下步骤:

  1. 实例化一个 BackgroundWorker 类;
  2. BackgroundWorker.DoWork() 方法为您完成脏活;
  3. 确保在设计时的组件模型属性窗口中设置了BackgroundWorker.WorkerReportsProgress = true
  4. 确保使用 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 the ShowDialog() method.

As to why exactly your Form is crashing is quite out of scope from now on. Please consider following the following steps:

  1. Instantiate a BackgroundWorker class;
  2. Make the BackgroundWorker.DoWork() method do the dirty work for you;
  3. Make sure you set the BackgroundWorker.WorkerReportsProgress = true in the component model property window in design;
  4. Make sure you ReportProgress() using the ReportProgress(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.

安穩 2024-10-15 09:09:54

您的应用程序很可能崩溃,因为您尝试直接从线程访问表单元素的属性(例如,当您调用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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文