1

So I want redirect my Console output to a TextBox to simulate in-GUI console. Now I saw this post:

https://stackoverflow.com/a/18727100/6871623

Which helps the redirection process.

However, since string is immutable, this means a new string will be allocated on every write and this isn't very efficient.

Therefore, I thought of using StringBuilder like:

public class ControlWriter : TextWriter
{
    private Control textbox;
    private StringBuilder builder;

    public ControlWriter(Control textbox)
    {
        this.textbox = textbox;
        builder = new StringBuilder();
    }

    public override void Write(char value)
    {
        builder.Append(value);
        textbox.Text = builder.ToString();
    }

    public override void Write(string value)
    {
        builder.Append(value);
        textbox.Text = builder.ToString();
    }

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

Looking at the code, it doesn't seem to improve performance much since a new string will be allocated every time we call builder.ToString(), mainly what we improve by this is the Append portion since now we won't be using string concat every time.

Is there a way to bind TextBox Text directly to StringBuilder? That is, appending or resetting the StringBuilder will automatically be reflected on GUI?

If that isn't possible for TextBox, is there another way of going around this?

Finally, is there a way to improve performance of the code above?

Everyone
  • 1,751
  • 13
  • 36
  • Wait hang-on.. is this a wpf app or a console app? anyway that aside, yes strings are immutable, textboxes are backed by a string somewhere along the line, can you go an edit the memory of a textbox to prod in more strings?... no. but even before this, how is this inefficiency causing you a problem ? – TheGeneral May 14 '19 at 01:03
  • @TheGeneral It is WPF but I wish to redirect all `Console` output to custom `TextWriter`. I'm doing that, but not very efficiently. I am not really inconvenienced by this and I can make do, but I just was wondering if there is a way to make it most efficient. It's for the sake of learning. – Everyone May 14 '19 at 01:05
  • The answer is not really, i mean, there will always be an allocation when you call ToString, there will always be an allocation when you update the textbox. – TheGeneral May 14 '19 at 01:07
  • @TheGeneral so there is no way to bind `Text` property directly to the stream of `StringBuilder` – Everyone May 14 '19 at 01:10
  • Binding wont stop an allocation though, but yes of course there is a way to bind, but not to a stringbuilder without some weird and wonderful new class, which wont really achieve much – TheGeneral May 14 '19 at 01:12
  • @TheGeneral can you elaborate? – Everyone May 14 '19 at 01:13
  • So as far as i can see your main question is about performance and allocations, you cant stop that, your second question is about binding to a StringBuilder, which is not really going to solve the first problem (even if you could) – TheGeneral May 14 '19 at 01:14
  • @TheGeneral i'm kind of asking for any way to make the performance of this much better. – Everyone May 14 '19 at 01:30
  • Side note: not related to the question but it is not a nice behavior to lie about encoding of your stream writer. Clearly there is no code that transform text to ASCII (even if simply dropping non-ASCII chars in regular string). – Alexei Levenkov May 14 '19 at 01:46
  • @AlexeiLevenkov I just took the code from the linked answer I attached to show the modification I made. I completely missed that part. You got a point – Everyone May 14 '19 at 01:48

1 Answers1

3

Since this is all hypothetical, I'll answer with what I can.

  1. The Console isn't a string, or a StringBuilder, it's actually a buffer, a multi-dimensional array of char (term used loosely).

  2. A TextBox is backed by a string.

  3. A StringBuilder is a single dimensional array of char, that can convert to a string with ToString()

So, updating a string with and endless stream of chars is going to bottom out sooner or later. Meaning, at some point you are going to be splattering a TextBox with endless amounts of characters that have no concept of lines.

If you want to get this more realistic, maybe you want a List or array instead of a string, but that makes its own problems. However, doing so will allow you to at least buffer a certain amount of data, or at least virtualise it in some way.

Also, you can't get over the allocations here, every time you do something with a string, you are allocating again.

Then you talk about binding... Binding is not going to help the allocations.

To answer your questions, you need to ask your self more questions. What is the best way you can visualise the data, can you virtualise it, how are you going to deal with lines.

For a simple exercise the textbox and what you are doing is fine. However, suggesting anything else on top of this is exceedingly hard and too broad.

halfer
  • 19,824
  • 17
  • 99
  • 186
TheGeneral
  • 79,002
  • 9
  • 103
  • 141
  • Thank you for the insight. I thought of using a `List` and `ListBox` and that can make it kind of better. But I guess a new problem arises with how all of that information is stored in the actual process memory (unlike an actual console where the output leaves process's memory space once it goes to Console). – Everyone May 14 '19 at 01:46