views:

1321

answers:

7

hi...i am trying to make a basic IRC client...but my problem is getting the text to display in a RTF box without it lagging

i settled on using threading, and i want to update the RTF box in a thread, but i cant because it gives me errors about the RTF box element not being static?

any insight? i will paste code if you guys want it


ok here is the code (do edits bump?)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Net;

namespace IrcClient
{
    public partial class mainWindow : Form
    {
        static IRC client;
        static string newLine, oldLine;

        public mainWindow()
        {
            InitializeComponent();
        }

        private void main()
        {

        }

        private void mainWindow_Load(object sender, EventArgs e)
        {
            client = new IRC("irc.freenode.net" ,6667, "jimi__hendrix");
            new Thread(new ThreadStart(update)).Start();

        }

        private static void update()
        {
            newLine = client.sr.ReadLine();

            Thread.Sleep(50);
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            client.privmsg(inputBox.Text);
            messageBox.AppendText(inputBox.Text + "\n");
            inputBox.Text = "";
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (newLine != oldLine)
            {
                messageBox.AppendText(newLine + "\n");
                oldLine = newLine;
            }
        }
    }

    class IRC
    {
        TcpClient connection;
        NetworkStream stream;
        public StreamWriter sw;
        public StreamReader sr;
        string nick;

        public IRC(string server, int port, string Nick)
        {
            try
            {
                connection = new TcpClient(server, port);
                stream = connection.GetStream();
                sr = new StreamReader(stream);
                sw = new StreamWriter(stream);
                nick = Nick;
                sw.WriteLine("PASS " + "caruso11");
                sw.Flush();
                sw.WriteLine("NICK " + nick);
                sw.Flush();
                sw.WriteLine("USER Jimi__Hendrix 8 irc.freenode.net :Jimi__Hendrix");
                sw.Flush();
            }

            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }

        public void privmsg(string msg)
        {
            sw.WriteLine(msg);
            sw.Flush();
        }

        public void parse(string msg)
        {

        }
    }
}


some of the methods are blank and some code could be cleaned up, but i want to get this done first...also, theres the code generated by visual studios that sets up the window

A: 

You could just make the RTF box static. I think that if you post some code it will be more helpful though.

Lucas McCoy
A: 

The RichTextBox is on the UI thread so you're not going to be able to access the RichTextBox unless your on the UI thread. How are you loading the content? How big is the content? Is the lag coming from loading the content or the RTF box parsing it?

bendewey
+1  A: 

I believe you are using Windows Forms. Check out this text about it, there is some remarks that you have to take care before making a thread accessing forms elements directly.

If this is not exactly your problem, please elaborate more the question.

Augusto Radtke
+4  A: 

In general, trying to update a Control from a thread other than the main thread will not work, due to limitations of Windows. If you need to call a method or set a property on the RTF box from your worker thread, you'll probably need to use Invoke or BeginInvoke. This might look like the following:

void MyThreadMethod()
{
    // stuff
    this.rtfBox.BeginInvoke( (MethodInvoker)(()=> this.rtfBox.Text = "foo") );
    // stuff
}

Edit: As others point out, if this is actually failing to compile due to an error about the control not being static, you're probably trying to reference a member variable from a static function, which is illegal. Posting code will help narrow down the problem.

Charlie
You'd also need to give the lambda expression an appropriate delegate type to convert to.
Jon Skeet
Thanks, I was afraid I might need to do that, but I didn't have a copy of VS2008 handy.
Charlie
so what would the propersnipit be
jimi hendrix
The updated code should work, please let me know if it doesn't.
Charlie
well i scraped that window class and started over...but i am getting errors with:<code>Thread t = new Thread(new ThreadStart(update));private void update() { this.richTextBox1.BeginInvoke((MethodInvoker)(() => this.richTextBox1.Text = "foo")); }</code>
jimi hendrix
bah...im not used to this forum's tags...
jimi hendrix
Can you update your question with the newer code and the specific errors you're getting?
Charlie
+1  A: 

RULE: You should not access one window from another thread.

Use this technique:

  • from your thread raise an event to update the RTF (with required text etc data)
  • on the GUI thread use the following:
  • use the "InvokeRequired" property to verify call is from GUI thread or not
  • Use the Invoke method (you will need a delegate for this)

BeginInvoke also works but the only problem is it does not really guarantee immediate start (it uses threadpool). I prefer to use the Invoke method instead.

Sesh
+1 for event driven model
Dennis Cheung
A: 

You're probably referencing a member variable of the form, instead of a static variable, thus the error.

Anyway this is quite a wrong approach, since UI elements can only be updated from the UI thread, otherwise you'll get a cross-thread operation exception. So you'll need to do Invoke() to the set-text method on the UI thread, which will eventually 'lag' too.

Not sure what you mean by 'lagging', you may try making your parent form double-buffered to reduce flicker.

arul
+1  A: 

Others have already mentioned what the problem you are experienced is, and how to solve it.

Not that having a separate worker thread is a bad idea, it seems odd that you need multiple threads because of performance reasons. It seems that for as something as simple as an IRC client, you should be able to do everything on one thread without any UI sluggishness. Maybe you can post some code so that we can see what the root of the problem is?

Giovanni Galbo