【问题标题】:Proper way to start a thread in a WinForm在 WinForm 中启动线程的正确方法
【发布时间】:2012-08-17 19:26:42
【问题描述】:

我有一个窗体 (Form1),当单击一个按钮时,我想在线程中打开另一个窗体 (form2)。

我想在线程中打开它,因为当它启动时,我会读取它并为 10k+ 行长文件的语法着色,这大约需要 5 或 6 分钟。

我的问题是我不知道“正确”的做法。我已经找到了如何做到这一点并且它工作正常,但我希望能够有一个进度条告诉我 Form2 的处理进度。 (可能带有后台工作对象)

这是我的布局

Form1 有一个 RichTextBoxes 和一个按钮,单击该按钮,它会在另一个线程中打开一个表单,为 form1 的 rtb 中的文本着色。

Form2 也有一个 Rtb,这个 rtb 有一个 ProcessAllLines 方法,它处理行并完成我想在另一个线程中完成的工作。

这就是我认为我遇到困难的原因。当表单等待加载时,文本框正在执行工作。

这是我打开 Form2 的方法:

    private void button1_Click(object sender, EventArgs e)
    {
        ColoringThread colorer = new ColoringThread(this.m_bruteView.Text);
        Thread theThread = new Thread(new ThreadStart(colorer.OpenColorWindow));
        theThread.Start();
    }

    public class ColoringThread
    {
        string text;
        public ColoringThread(string initText)
        {
            text = initText;
        }
        public void OpenColorWindow()
        {
            Form2 form2 = new Form2(text);
            form2.ShowDialog();
        }
    };

这是 form2 的工作原理:

    string initText;
    public Form2(string initTextInput)
    {
        initText = initTextInput;
        InitializeComponent();
    }


private void InitializeComponent()
    {
        this.m_ComplexSyntaxer = new ComplexSyntaxer.ComplexSyntaxer();
        this.SuspendLayout();
        // 
        // m_ComplexSyntaxer
        // 
        this.m_ComplexSyntaxer.Dock = System.Windows.Forms.DockStyle.Fill;
        this.m_ComplexSyntaxer.Location = new System.Drawing.Point(0, 0);
        this.m_ComplexSyntaxer.Name = "m_ComplexSyntaxer";
        this.m_ComplexSyntaxer.Size = new System.Drawing.Size(292, 273);
        this.m_ComplexSyntaxer.TabIndex = 0;
        this.m_ComplexSyntaxer.Text = initText;
        this.m_ComplexSyntaxer.WordWrap = false;

        // THIS LINE DOES THE WORK
        this.m_ComplexSyntaxer.ProcessAllLines();
        // 
        // Form2
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(292, 273);
        this.Controls.Add(this.m_ComplexSyntaxer);
        this.Name = "Form2";
        this.Text = "Form2";
        this.ResumeLayout(false);
    }

这里是完成工作的地方:

    public void ProcessAllLines()
    {
        int nStartPos = 0;
        int i = 0;
        int nOriginalPos = SelectionStart;
        while (i < Lines.Length)
        {
            m_strLine = Lines[i];
            m_nLineStart = nStartPos;
            m_nLineEnd = m_nLineStart + m_strLine.Length;
            m_nLineLength = m_nLineEnd - m_nLineStart;

            ProcessLine(); // This colors the current line!
            i++;

            nStartPos += m_strLine.Length + 1;
        }
        SelectionStart = nOriginalPos;
    }

Sooo,打开这个 form2 并让它向 Form1 报告进度以显示给用户的“正确”方式是什么? (我之所以问,是因为有人告诉我这不是正确的做法,我显然会受到“跨线程”违规?)

【问题讨论】:

标签: c# winforms multithreading


【解决方案1】:

我想在线程中打开它,因为当它启动时,我会读取它并为 10k+ 行长文件的语法着色,这大约需要 5 或 6 分钟。

为什么不在一个单独的线程中读取数据,然后将 UI 本身与第一个表单保持在同一个线程上?

根据我的经验,如果您只使用一个线程进行 UI 操作,它会大大简化工作。

至于你应该如何启动一个新线程来读取数据,有多种选择:

  • 你可以使用BackgroundWorker;这可能会使进度报告更简单。见the MSDN article for more information
  • 直接新建Thread并启动
  • 使用带有ThreadPool.QueueUserWorkItem 的线程池线程
  • 如果您使用的是 .NET 4,请使用 Task.Factory.StartNew

【讨论】:

  • 对不起,数据(文本10k+行)没有读入,只是传递给Form2对象的构造函数,传递给它的RichTextBox。 .. 我希望 form1 在 Form2 加载时能够响应。我认为没有线程就无法实现。
  • @user1596244:那么你需要对数据做些什么呢? all 是创建 RichTextBox 的工作,还是先对其执行更多处理?
  • 所有的工作都是在为每一行的语法着色时完成的,我遍历每一行并寻找特定的模式,如果发现它以某种方式着色。我在显示表单之前给语法上色,这样它就不会只是作为一个无响应的白色窗口呆在那里,直到它完成每一行的处理。
  • @user1596244:那么听起来工作应该在单独的线程中完成,而不是在 GUI 线程中。
  • 所以我应该正常从form1调用form2,“new form2; form2.show dialog;” ...然后在 form2 中,在另一个线程中执行其着色操作,并让它显示“此表单将在着色完成时填充”的文本,然后在着色完成时将文本扔到文本区域?
【解决方案2】:

在我看来,另一种形式不需要在另一个显式线程中运行。

确定您希望在另一个线程(或后台工作程序)中完成长时间的工作,但您只想调用另一个表单,而另一个表单将在另一个线程(或后台工作程序)中执行任务。

【讨论】:

  • 如果我在 form1 上按下按钮时调用的方法中调用 form2.showdialog;在 form2 加载之前,我的 form1 用户界面变得无响应。但是,如果我在另一个线程中调用 form2,那么 form1 UI 在 form2 加载时是响应式的,这就是我想要的,所以用户在 form2 加载时有事情要做
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-02
  • 1970-01-01
  • 2013-03-24
  • 1970-01-01
  • 2014-11-23
  • 1970-01-01
  • 2013-10-03
相关资源
最近更新 更多