2

I got a problem with my textbox.
I have a class that represents the GUI thread and a class for the worker thread that does some networking stuff and then has to add the log to the textbox in the GUI thread so you can see what is happening in the background.
However, I have the problem that nothing happens on the GUI, only the debug information that addLine() was called is in the console.
The method addLine() that should add the log gets called but it seems like AppendText() just does nothing.
I am pretty sure this has to do something with the threads but I am not sure how I shall solve this.

Here is the code:

Worker Thread:

    Form1 form = new Form1();
    // This method gets called in the worker thread when a new log is available
    private void HandleMessage(Log args)
    {
        // Using an instance of my form and calling the function addLine()
        form.addLine(args.Message);
    }

GUI Thread:

    // This method gets called from the worker thread
    public void addLine(String line)
    {
        // Outputting debug information to the console to see if the function gets called, it does get called
        Console.WriteLine("addLine called: " + line);
        // Trying to append text to the textbox, console is the textbox variable
        // This pretty much does nothing from the worker thread
        // Accessing it from the GUI thread works just fine
        console.AppendText("\r\n" + line);

        // Scrolling to the end
        console.SelectionStart = console.Text.Length;
        console.ScrollToCaret();
    }

I tried to do some Invoke stuff already but failed at using it properly.
The GUI either locked itself or it just continued to do nothing.

user1137183
  • 119
  • 2
  • 11

1 Answers1

8

You can't take to a winforms UI if you aren't on the UI thread. Try:

console.Invoke((MethodInvoker)delegate {
    console.AppendText("\r\n" + line);

    console.SelectionStart = console.Text.Length;
    console.ScrollToCaret();
});

which will bump it onto the UI thread.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • How would I access the textbox from the worker thread? If I try to access it with form.console.Invoke() it still doesn't work and console.Invoke() of course will get me an error since the textbox is declared in the GUI class. – user1137183 Jul 22 '12 at 19:28
  • 1
    @user do you see the `console.Invoke(...)` in the above? that is what switches to the UI thread. If it still doesn't work, you have bug unrelated to threads. Unless, of course, the UI thread is already tied up in knots and can't process the event-queue to handle the above. – Marc Gravell Jul 22 '12 at 19:29
  • Yes, I forgot to mention that they are in different classes. So console is defined in the GUI class but not in the worker class. Sorry for that. So if I try to use console.Invoke I of course get an error because console is not defined in the worker class. – user1137183 Jul 22 '12 at 19:34
  • It does, I access console via form.console, as shown in the code above: Form1 form = new Form1(); – user1137183 Jul 22 '12 at 19:38
  • @user1137183 and the code I show above goes inside `addLine`. Not seeing the problem... – Marc Gravell Jul 22 '12 at 19:39
  • Ahh it goes into addLine, that explains a few things. It still doesn't work though. So the thread is not the problem? addLine() gets called since I get the confirmation in the console but my textbox stays the same. – user1137183 Jul 22 '12 at 19:42
  • @user1137183 and does the `console.*****` code run? if so, add a breakpoint, and debug it to find whyu – Marc Gravell Jul 22 '12 at 19:43
  • 1
    @Marc - He's creating a new form instead of using the existing one. Good luck. – Hans Passant Jul 22 '12 at 19:50
  • @HansPassant The function addLine() does get executed so it must be in the existing one? – user1137183 Jul 22 '12 at 19:56
  • @user1137183 I think we need to see this in reproducible form, or you're going to have to debug it; not enough to go on – Marc Gravell Jul 22 '12 at 20:04
  • @HansPassant Oh damn, you are right. Didn't even notice that. I fixed it now by passing the correct form to the HandleMessage() method. Thanks for the tip. – user1137183 Jul 22 '12 at 20:05