C# Console.SetOut 跨线程操作无效

本文关键字:操作 无效 线程 Console SetOut | 更新日期: 2023-09-27 18:35:24

我有一个控制台应用程序,现在我想为它制作一个GUI,我想将控制台文本发送到文本框,我知道这被问得更多,但我无法让它工作:S :S

我在 Form1 加载中使用了这段代码:

private void Form1_Load(object sender, EventArgs e)
{
    Console.SetOut(new TextBoxWriter(consoleTextbox));
}

这是 TextBoxWriter 类:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace KLFClient
{
    public class TextBoxWriter : TextWriter
    {
        TextBox _output = null;
        public TextBoxWriter(TextBox output)
        {
            _output = output;
        }
        public override void Write(char value)
        {
            base.Write(value);
            _output.AppendText(value.ToString());
        }
        public override Encoding Encoding
        {
            get { return System.Text.Encoding.UTF8; }
        }
    }
}

但是当我启动程序并启动服务器系统时,它会返回此错误:

System.Windows.Forms 中发生了类型为"System.InvalidOperationException"的未处理异常.dll

其他信息:跨线程操作无效:从创建它的线程以外的线程访问的控件"consoleTextbox"。

C# Console.SetOut 跨线程操作无效

控件不能由 UI 线程以外的线程更改。您的控制台正在运行自己的线程。它正在调用您的类并尝试更改文本框文本。

若要停止此操作,需要确保文本更改操作在 UI 线程上进行。你可以通过使用说,Invoke来做到这一点:

_output.Invoke(new MethodInvoker(() => _output.AppendText(value.ToString())));

只能从 UI 线程访问 Windows 窗体 UI 控件。可以在控件上使用 Invoke() 方法将操作排队以在该线程上运行。例如,您可以将 Write() 的实现更改为:

    public override void Write(char value)
    {
        var text = value.ToString();
        this._output.Invoke(new Action(() => this._output.AppendText(text)));
    }

正如错误试图告诉您的那样,您无法从非 UI 线程与 UI 交互。

后台线程正在尝试写入控制台,使您的流与来自错误线程的文本框交互。

相反,应在 Write() 中调用 BeginInvoke() 方法,以便在 UI 线程上异步运行代码。