跨线程操作?

时间:2015-03-28 02:08:14

标签: c# multithreading backgroundworker

第一关我甚至不确定C#Cross-Thread Operation是什么,所以看到这个调试信息从一开始就让我大吃一惊 - Cross-thread operation not valid: Control 'panel1' accessed from a thread other than the thread it was created on.我只是想写一个文本框来显示进度我的程序。为简洁起见,下面的代码中使用了Thread.Sleep()。当我的代码命中行panel1.Controls.Add(txt);时,我收到调试消息。这里是完整的代码:

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
    private DateTime now = DateTime.Now;
    private int i = 0;
    TextBox txt = new TextBox();

     public Form1()
    {
        InitializeComponent();
        backgroundWorker1.WorkerReportsProgress = true;
        backgroundWorker1.WorkerSupportsCancellation = false;
        backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
        backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
    }

    private void button1_Click(object sender, EventArgs e)
    {
            backgroundWorker1.RunWorkerAsync();
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
            panel1.Controls.Add(txt);
            MethodOne();
            MethodTwo();
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Value = e.ProgressPercentage;
    }

    private void MethodOne()
    {
        txt.Text = "MethodOne Process Has Begun....." + now;
        Thread.Sleep(100);
        txt.Text = "MethodOne Process Has Finished....." + now;
    }
    private void MethodTwo()
    {
        txt.Text = "MethodTwo Process Has Begun....." + now;
        Thread.Sleep(100);
        txt.Text = "MethodTwo Has Finished....." + now;
    }
}
}

如果我需要提供有关我的Windows窗体设置方式的更多详细信息或更多信息,请与我们联系。

2 个答案:

答案 0 :(得分:2)

您无法直接从BackgroundWorker线程访问UI控件。 UI控件位于单独的线程上,因此出现错误。这是不允许的:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    panel1.Controls.Add(txt);
    ...
}

BackgroundWorker允许您传递一个数字(通常表示一个百分比),另一个传回(可能是任何内容,例如您的文本)。我建议的是:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    var bgw = (BackgroundWorker)sender;

    bgw.ReportProgress(33, "MethodOne Process Has Begun.....");
    MethodOne();

    bgw.ReportProgress(66, "MethodTwo Process Has Begun.....");
    MethodTwo();

    bgw.ReportProgress(100, "All Processes Finished.");
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage;

    var statusMessage = e.UserState.ToString();
    // Display statusMessage in an appropriate control, i.e. a Label
}

答案 1 :(得分:1)

从不同线程在UI上发生的操作需要一个称为Invoke的特殊编组过程。如果您不使用其他线程的Invoke,则会发生错误。