2

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

但是,periodsLabel.Text 并没有像预期的那样改变!如何在后台执行其他操作时更新 UI?

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

2 回答 2

2

首先,以我的拙见,你不应该像你一样扔掉一个线程。

最佳实践是使用BackgroundWorker线程。

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

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

  1. 实例化一个BackgroundWorker类;
  2. BackgroundWorker.DoWork()方法为你做脏活;
  3. 确保BackgroundWorker.WorkerReportsProgress = true在设计的组件模型属性窗口中设置;
  4. 确保您ReportProgress()使用该ReportProgress(int)方法。

请参阅这个问题(C#:使用单独的线程填充 UI。)和我的代码示例,我认为它只是解释了 BackgroundWorker 类实例的使用。

注意:仍在寻找另一个例子。

编辑#1

这是一篇关于线程的好文章:C# 中的线程。
因为Jon Skeet是这么说的!.NET 中的多线程:介绍和建议

于 2010-12-18T05:28:14.867 回答
0

您的应用程序可能会崩溃,因为您试图直接从线程(例如,当您调用 PeriodsLabel.Text 时)访问表单元素的属性,而不是使用线程中的 BeginInvoke 来调用表单上的方法,该方法将执行该属性访问。

但是将 BackgroundWorker 类用于此类事情会更好/更简单。

于 2010-12-18T05:51:58.657 回答