在WinForm中启动线程的正确方法

时间:2012-08-17 19:26:42

标签: c# winforms multithreading

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

我想在一个帖子中打开它,因为当它启动时我读取了10k +行长文件的颜色语法,大约需要5或6分钟。

我的问题是我不知道“正确”的方式。我已经找到了如何做到这一点并且工作正常,但我希望能够有一个进度条告诉我Form2与其处理的距离。 (可能有一个Background worker对象)

这是我的布局

Form1有一个RichTextBoxes和一个buton,单击按钮,它会在另一个线程中打开一个表单,为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报告进度以向用户显示? (我问,因为有人告诉我这不是正确的做法,我会明显受到“跨线程”的侵犯吗?)

2 个答案:

答案 0 :(得分:2)

  

我想在一个帖子中打开它,因为当它启动时我读取了10k +行长文件的颜色语法,大约需要5或6分钟。

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

根据我的经验,如果你只使用一个线程进行UI操作,它会让生活变得更加简单。

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

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

答案 1 :(得分:1)

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

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