0

I have looked for a solution for my problem, but I couldn't find it yet.

I'm coding a bot which will be connected to an irc server. I want the user to have access to a win forms window where it is possible to input the server, channel, and so on.

This is the window:

enter image description here

I have set the console output to update my textbox with the code in the main program. With this, I get all text coming from the child classes into my text box.

static class Program
{
    private static Form1 Form1;
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {

        using (var consoleWriter = new ConsoleWriter())
        {
            consoleWriter.WriteLineEvent += consoleWriter_WriteLineEvent;

            Console.SetOut(consoleWriter);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Form1 = new Form1();
            Application.Run(Form1);
        }
    }

    static void consoleWriter_WriteLineEvent(object sender, ConsoleWriterEventArgs msg)
    {
        var message = msg.Value;
        Form1.statusTextBox.AppendText(message + "\r\n");
    }
}

public class ConsoleWriter : TextWriter
{
    public override Encoding Encoding { get { return Encoding.UTF8; } }

    public override void Write(string value)
    {
        if (WriteEvent != null) WriteEvent(this, new ConsoleWriterEventArgs(value));
        base.Write(value);
    }

    public override void WriteLine(string value)
    {
        if (WriteLineEvent != null) WriteLineEvent(this, new ConsoleWriterEventArgs(value));
        base.WriteLine(value);
    }

    public event EventHandler<ConsoleWriterEventArgs> WriteEvent;
    public event EventHandler<ConsoleWriterEventArgs> WriteLineEvent;
}

public class ConsoleWriterEventArgs : EventArgs
{
    public string Value { get; private set; }
    public ConsoleWriterEventArgs(string value)
    {
        Value = value;
    }
}

Now I call this in my Form1, when the button "Connect" is clicked on:

 gbaIrcBot.Connect(server, null, port, nick, channelList);

Inside the gbaIrcBot.Connect(), i have among other things:

    private void ReadStream()
    {
        string inputLine;
        while ((inputLine = _streamReader.ReadLine()) != null)
        {
            var splitInput = inputLine.Split(new[] { ' ' });
            if (splitInput.ElementAt(0) == "PING") { Pong(splitInput.ElementAt(1)); continue;}

            switch (splitInput.ElementAt(1))
            {
                case "001":         foreach (var channel in ChannelList) JoinChannel(channel);  break;
                case "PRIVMSG":     ProcessPrivMsg(splitInput);                                 break;
                case "433":         SetNick("AlternativeBOT");                                  break;
                default: Console.WriteLine(inputLine); break;
            }
        }
    }

This method is responsible for reading all inputs from the irc server. When I get messages from the server, I send it to the console, which updates the textbox in Form1. It MUST be an infinite loop.

All this works well if I dont create a thread to keep my UI not frozen. This is an example:

enter image description here

When I try to create a thread, My Form1 throws an exception saying its a cross-thread message, and I cannot update it from outside.

Any idea to solve it?

Th3B0Y
  • 884
  • 1
  • 12
  • 30
  • if you are using background worker, you should be able to use OnProgressChanged event to update the UI. If you need to change a setting in the running thread, you can cancel the thread and start a new one with the updated settings. – jle Feb 26 '14 at 17:42

2 Answers2

0

WinForms UI updates have to be performed on the UI thread. Try this approach:

How to update the GUI from another thread in C#?

Community
  • 1
  • 1
jlew
  • 10,491
  • 1
  • 35
  • 58
0

The update on the form must be done in the window update thread.

You can force the execution in such thread by wrapping your call with BeginInvoke().

Change

Form1.statusTextBox.AppendText(message + "\r\n");

to

Form1.BeginInvoke(() => Form1.statusTextBox.AppendText(message + "\r\n"));
Mau
  • 14,234
  • 2
  • 31
  • 52