C# 正在将Console.WriteLine()重定向到Textbox

C# 正在将Console.WriteLine()重定向到Textbox,c#,redirect,user-interface,console.writeline,C#,Redirect,User Interface,Console.writeline,我正在Visual Studio 2010中使用C#构建此应用程序 基本上有两个文件,form1.cs(windows窗体)和program.cs(所有逻辑所在) 有一个运行按钮和一个空白文本框 当用户点击运行按钮时,program.cs将执行一些任务,并使用控制台上的Console.WriteLine()不断打印进度(命令提示符) 问题:如何打印到form1上的文本框而不是打印到命令提示符? 我需要在没有任何用户操作的情况下不断打印进度 提前谢谢 顺便说一下,它不一定是一个文本框,它可以是一个

我正在Visual Studio 2010中使用C#构建此应用程序

基本上有两个文件,form1.cs(windows窗体)和program.cs(所有逻辑所在)

有一个运行按钮和一个空白文本框

当用户点击运行按钮时,program.cs将执行一些任务,并使用控制台上的
Console.WriteLine()
不断打印进度(命令提示符)

问题:如何打印到form1上的文本框而不是打印到命令提示符? 我需要在没有任何用户操作的情况下不断打印进度

提前谢谢


顺便说一下,它不一定是一个文本框,它可以是一个标签或其他可以接收文本的东西。我选择textbox是因为它对我来说更有意义。

不知道它是否能工作,但您可以尝试重定向控制台输出

使用
Console.SetOut()
并创建
TextWriter
的派生,它覆盖
WriteLine()
方法,只需将方法参数分配给
TextBox.Text

应该有效。

文本框
放在表单(
多行
已启用)或文本区域上,然后您可以在循环中执行操作

txtOutput.Text += "Progress " + percent + "% completed." + Environment.NewLine();

首先,创建一个新的
文本编写器
,它可以写入文本框。它只需要重写接受字符的
Write
方法,但这将是非常低效的,因此最好至少用字符串重写方法

public class ControlWriter : TextWriter
{
    private Control textbox;
    public ControlWriter(Control textbox)
    {
        this.textbox = textbox;
    }

    public override void Write(char value)
    {
        textbox.Text += value;
    }

    public override void Write(string value)
    {
        textbox.Text += value;
    }

    public override Encoding Encoding
    {
        get { return Encoding.ASCII; }
    }
}
在本例中,我让它只接受一个
控件
,它可以是一个
文本框
、一个
标签
,或者其他任何东西。如果您想将其更改为一个
标签
,则可以

然后,只需将控制台输出设置为此编写器的新实例,指向某个文本框或标签:

Console.SetOut(new ControlWriter(textbox1));
如果您希望将输出写入控制台和文本框,我们可以使用此类创建一个将写入多个写入器的写入器:

public class MultiTextWriter : TextWriter
{
    private IEnumerable<TextWriter> writers;
    public MultiTextWriter(IEnumerable<TextWriter> writers)
    {
        this.writers = writers.ToList();
    }
    public MultiTextWriter(params TextWriter[] writers)
    {
        this.writers = writers;
    }

    public override void Write(char value)
    {
        foreach (var writer in writers)
            writer.Write(value);
    }

    public override void Write(string value)
    {
        foreach (var writer in writers)
            writer.Write(value);
    }

    public override void Flush()
    {
        foreach (var writer in writers)
            writer.Flush();
    }

    public override void Close()
    {
        foreach (var writer in writers)
            writer.Close();
    }

    public override Encoding Encoding
    {
        get { return Encoding.ASCII; }
    }
}

我用这样的东西作为列表框:

    public class ListBoxWriter : TextWriter //this class redirects console.writeline to debug listbox
{
    private readonly ListBox _list;
    private StringBuilder _content = new StringBuilder();

    public ListBoxWriter(ListBox list)
    {
        _list = list;
    }

    public override Encoding Encoding
    {
        get { return Encoding.UTF8; }
    }
    public override void Write(char value)
    {
        base.Write(value);
        _content.Append(value);

        if (value != '\n') return;
        if (_list.InvokeRequired)
        {
            try
            {
                _list.Invoke(new MethodInvoker(() => _list.Items.Add(_content.ToString())));
                _list.Invoke(new MethodInvoker(() => _list.SelectedIndex = _list.Items.Count - 1));
                _list.Invoke(new MethodInvoker(() => _list.SelectedIndex = -1));
            }
            catch (ObjectDisposedException ex)
            {
                Console.WriteLine(Resources.Exception_raised + " (" + ex.Message + "): " + ex);
            }
        }
        else
        {
            _list.Items.Add(_content.ToString());
            _list.SelectedIndex = _list.Items.Count - 1;
            _list.SelectedIndex = -1;
        }
        _content = new StringBuilder();
    }
}
在我的主要申请中:

_writer = new ListBoxWriter(DebugWin); // DebugWin is the name og my listbox

控制台放线(_-writer)

问题是,循环在program.cs中,它无法识别文本框,文本框只存在于form1.cs中,所以不要使用控制台应用程序…只需使用一个简单的GUI应用程序即可。我是否将“console.SetOut(new TextboxWriter(textbox1));”放在带有program.cs的Main()中?program.cs无法识别form1.cs中的textbox1,并且该textbox1在程序中不存在。cs@sora0419不,您应该将其放在表单的定义中。当我创建ControlWriter时,我得到一个错误,它说“'ControlWriter'没有实现继承的抽象成员'System.IO.TextWriter.Encoding.get'”我遗漏了什么?@sora0419刚刚为编码添加了一个实现。我尝试了第一种方法。程序停止打印到控制台,但是文本框中也没有打印任何内容。我将ControlWriter类放在命名空间Form1内,但放在公共部分类Form1外:Form{}。在初始化Component()之后,我将“Console.SetOut(新的ControlWriter(textbox1));”放在Form1类中;我是不是误解了什么,把函数放错地方了?虽然你原来的问题似乎已经得到了回答,但如果你正在向文本框发送大量更新,要当心,因为你可能会淹没消息队列,导致表单变得毫无响应。形态反应也取决于“某些计算”的强度。您可能需要考虑后台进程线程,它将进度报告回窗体。@ Rikdavin注意到,这样的选择将需要有能力将所有控制台写入更改为其他内容。如果他无法控制该代码(即,它是库代码),那么这可能不是一个选项,也可能只是不实用。
    public class ListBoxWriter : TextWriter //this class redirects console.writeline to debug listbox
{
    private readonly ListBox _list;
    private StringBuilder _content = new StringBuilder();

    public ListBoxWriter(ListBox list)
    {
        _list = list;
    }

    public override Encoding Encoding
    {
        get { return Encoding.UTF8; }
    }
    public override void Write(char value)
    {
        base.Write(value);
        _content.Append(value);

        if (value != '\n') return;
        if (_list.InvokeRequired)
        {
            try
            {
                _list.Invoke(new MethodInvoker(() => _list.Items.Add(_content.ToString())));
                _list.Invoke(new MethodInvoker(() => _list.SelectedIndex = _list.Items.Count - 1));
                _list.Invoke(new MethodInvoker(() => _list.SelectedIndex = -1));
            }
            catch (ObjectDisposedException ex)
            {
                Console.WriteLine(Resources.Exception_raised + " (" + ex.Message + "): " + ex);
            }
        }
        else
        {
            _list.Items.Add(_content.ToString());
            _list.SelectedIndex = _list.Items.Count - 1;
            _list.SelectedIndex = -1;
        }
        _content = new StringBuilder();
    }
}
_writer = new ListBoxWriter(DebugWin); // DebugWin is the name og my listbox