C# 跨线程操作?

C# 跨线程操作?,c#,multithreading,backgroundworker,C#,Multithreading,Backgroundworker,首先,我甚至不确定什么是C#交叉线程操作,因此,看到这个调试消息让我从一开始就大吃一惊-跨线程操作无效:控件“panel1”是从创建它的线程以外的线程访问的。我只是试图写入一个文本框以显示我的过程的进度Thread.Sleep()。当我的代码点击行panel1.Controls.Add(txt)时,我收到调试消息以下是完整的代码: namespace WindowsFormsApplication1 { public partial class Form1 : Form { privat

首先,我甚至不确定什么是C#
交叉线程操作
,因此,看到这个调试消息让我从一开始就大吃一惊-
跨线程操作无效:控件“panel1”是从创建它的线程以外的线程访问的。
我只是试图写入一个文本框以显示我的过程的进度<为了简洁起见,下面的代码中使用了code>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窗体的任何进一步详细信息或更多信息,请告诉我。

从不同线程在UI上执行的操作需要一个称为的特殊封送处理过程。如果不使用来自另一个线程的调用,则会发生错误。

在UI上从不同线程执行的操作需要一个称为调用的特殊封送处理。如果不使用来自另一个线程的调用,则会发生错误。

在UI上从不同线程执行的操作需要一个称为调用的特殊封送处理。如果不使用来自另一个线程的调用,则会发生错误。

在UI上从不同线程执行的操作需要一个称为调用的特殊封送处理。如果不使用来自其他线程的调用,则会发生错误。

您无法直接从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
}

您不能直接从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
}

您不能直接从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
}

您不能直接从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
}

问题是我正试图通过backgroundWorker1\u DoWork()过程修改我的表单?是的。您可能应该在同一线程上修改表单;我认为在
BackgroundWorker
中修改表单没有任何好处
BackgroundWorker
适用于不涉及表单的长时间运行的操作(已经是线程安全的进度指示器除外)。有关调用的代码示例,请参阅。问题是我正试图通过backgroundWorker1\u DoWork()过程修改我的表单?是的。您可能应该在同一线程上修改表单;我认为在
BackgroundWorker
中修改表单没有任何好处
BackgroundWorker
适用于不涉及表单的长时间运行的操作(已经是线程安全的进度指示器除外)。有关调用的代码示例,请参阅。问题是我正试图通过backgroundWorker1\u DoWork()过程修改我的表单?是的。您可能应该在同一线程上修改表单;我认为在
BackgroundWorker
中修改表单没有任何好处
BackgroundWorker
适用于不涉及表单的长时间运行的操作(已经是线程安全的进度指示器除外)。有关调用的代码示例,请参阅。问题是我正试图通过backgroundWorker1\u DoWork()过程修改我的表单?是的。您可能应该在同一线程上修改表单;我认为在
BackgroundWorker
中修改表单没有任何好处
BackgroundWorker
适用于不涉及表单的长时间运行的操作(已经是线程安全的进度指示器除外)。请参阅Invoke的代码示例。我不确定这会有多奇怪。。。当您创建了一个后台线程并将其设置为工作状态时。正如Robert所说-控件不能从与创建它们的线程不同的线程访问。我不确定这有多奇怪。。。当您创建了一个后台线程并将其设置为工作状态时。正如Robert所说-控件不能从与创建它们的线程不同的线程访问。我不确定这有多奇怪。。。当您创建了一个后台线程并将其设置为工作状态时。正如Robert所说-控件不能从与创建它们的线程不同的线程访问。我不确定这有多奇怪。。。当您创建了一个后台线程并将其设置为工作状态时。正如Robert所说-无法从不同于创建控件的线程访问控件。这可能也会起作用,因为正在从UI线程上封送的事件调用
panel1.controls.Add
。注意
progressBar1.Value=e.ProgressPercentage
已经起作用了。将panel1.Controls.Add(txt)放在button1_Click()事件或Form1()事件下是否更好(或者更重要)?这可能也起作用,因为
panel1.Controls.Add
是从UI线程上封送的事件调用的。注意
progressBar1.Value=e.ProgressPercentage
已经起作用了。放置panel1.Cont是否更好(或者更重要)