跨线程操作无效:Control';rchsdtOut';从创建它的线程以外的线程访问

本文关键字:线程 操作 访问 创建 无效 rchsdtOut Control | 更新日期: 2023-09-27 18:20:53

所以我得到了这个跨线程错误,我无法解决它。这是我试图篡改它之前的基本代码。

基本上,代码要做的是调用一个批处理文件,然后再调用一个java文件。输出数据随后被实时重定向到控制台。当我只是将输出重定向到C#控制台时,它工作得很好。但我想把同样的信息打印到应用程序的富文本框中。VS 2010在rchsdtOut.Text=e.Data.ToString()上抱怨;跨线程操作无效:控件"rchsdtOut"是从创建它的线程以外的线程访问的。

我试着查了一下,我承认我是线程的新手,所以如果能帮助我轻松完成这项任务,我将不胜感激。

   //Declare and instantiate a new process component.
    System.Diagnostics.Process process1;
    process1 = new System.Diagnostics.Process();
    process1.StartInfo.UseShellExecute = false;
    process1.StartInfo.RedirectStandardOutput = true;
    process1.StartInfo.CreateNoWindow = true;
    process1.StartInfo.FileName = "cmd.exe";
    process1.StartInfo.Arguments = "BATFile.bat";
    process1.OutputDataReceived += (s, a) => myMethod(a);
    process1.Start();
    process1.BeginOutputReadLine(); 
    process1.WaitForExit();
    process1.Close(); 

    private void myMethod(DataReceivedEventArgs e) {       
       if (e.Data != null)
        {         
           rchsdtOut.Text = e.Data.ToString();
           Console.WriteLine(e.Data.ToString());
        } 
    }//end of private

跨线程操作无效:Control';rchsdtOut';从创建它的线程以外的线程访问

试试这一行:

process1.OutputDataReceived += (s, a) => rchsdtOut.Invoke(new System.Action(()=> myMethod(a)));

从创建WinForms控件的线程以外的线程访问WinForms控件是不合法的。您需要使用InvokeBeginInvoke将控件返回到相应的线程。

private void myMethod(DataReceivedEventArgs e) {       
  if (e.Data != null) {
    Action action = () => rchstdOut.Text = e.Data.ToString();
    rchstdOut.Invoke(action, null);
    Console.WriteLine(e.Data.ToString());
  }
}

您不能从创建表单控件的线程以外的线程访问表单控件。您将需要创建两个线程都可以访问的其他对象。生产者-消费者问题

当您的方法从另一个线程调用时,只能从UI线程升级rchsdtOut。有几种解决方案。如果你想有一个通用的方法来更新控件,你可以检查控件。InvokeRequired属性(或WPF中的this.Dispatcher.CheckAccess())并使用委托。

    private delegate void UpdateTextControlDelegate(Control control, string text);
    private void UpdateTextControl(Control control, string text)
    {
        if (control.InvokeRequired)
        {
            Invoke(new UpdateTextControlDelegate(UpdateTextControl), new object[] { control, text});
            return;
        }
        control.Text = text;
    }

if (e.Data != null)
{         
     UpdateTextControl(rchsdtOut, e.Data.ToString());
     Console.WriteLine(e.Data.ToString());
}