简体   繁体   中英

C# Console.SetOut Cross-thread operation not valid

I have a console application and I want to make a GUI for it now I want to send the console text to a textbox I know this is asked more but I can't get it to work :S :S

I used this code in my Form1 Load :

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

and this is the TextBoxWriter class :

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; }
        }
    }
}

But when I start my program and start my server system it returns this error :

An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll

Additional information: Cross-thread operation not valid: Control 'consoleTextbox' accessed from a thread other than the thread it was created on.

Controls cannot be changed by Threads other than the UI Thread. Your Console is running its own Thread.. and it is calling into your class and attempting to change the Textboxes text.

To stop this, you need to make sure that the text change operation takes place on the UI thread. You can do this by using say, Invoke :

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

Windows forms UI controls can only be accessed from the UI thread. You can use the Invoke() method on a control to queue up an action to run on said thread. For example, you could change your implementation of Write() to be:

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

As the error is trying to tell you, you cannot interact with the UI from a non-UI-thread.

A background thread is trying to write to the console, making your stream interact with the textbox from the wrong thread.

Instead, you should call the BeginInvoke() method in Write() to asynchronously run your code on the UI thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM