Thread: c# mulithreading

  1. #1
    Registered User
    Join Date
    Mar 2009
    Posts
    23

    Question c# mulithreading

    I'm working on a telnet chat server that starts out with a Windows Form. It has a button which starts the server and a textbox that logs the process, people that login and people that logout, stuff like that.

    When I start the server I create a new thread else the whole UI freezes. I have a fuction called AddToText which sends information to the texbox on the UI.

    Code:
    Public Void AddToText(string textoadd)
    {
    txtStatus.Text = txtStatus.Text + "\r\n" + texttoadd;
    }
    how would I invoke this function from a different thread. I've tried so many things, using delegates but It just doesn't work. I'm also in a different class when I want to invoke it.

    Help PLZ!

  2. #2
    Confused Magos's Avatar
    Join Date
    Sep 2001
    Location
    Sweden
    Posts
    3,145
    MagosX.com

    Give a man a fish and you feed him for a day.
    Teach a man to fish and you feed him for a lifetime.

  3. #3
    Registered User
    Join Date
    Mar 2009
    Posts
    23
    that doesnt make any sense to me. Also Im not using a background thread, just a normal one by new Thread(Server.Connection).Start().

  4. #4
    Confused Magos's Avatar
    Join Date
    Sep 2001
    Location
    Sweden
    Posts
    3,145
    A thread is a thread, whether it's a background worker or not.
    And to invoke you call Invoke, or BeginInvoke if deadlocks are a concern.
    MagosX.com

    Give a man a fish and you feed him for a day.
    Teach a man to fish and you feed him for a lifetime.

  5. #5
    Registered User
    Join Date
    Mar 2009
    Location
    england
    Posts
    209
    Make a delegate to handle your cross thread operation. Example:

    Code:
    public delegate void AddToTextCrossThreadDelegate(string textoadd);
    
    public void AddToText(string textoadd)
    {
        if (this.txtStatus.InvokeRequired)
            this.txtStatus.BeginInvoke(new AddToTextCrossThreadDelegate(this.AddToText), textoadd);
        else
            this.txtStatus.Text += ("\r\n" + textoadd);
    }
    Last edited by theoobe; 03-09-2009 at 07:37 AM.

  6. #6
    Registered User
    Join Date
    Mar 2009
    Posts
    23
    Quote Originally Posted by theoobe View Post
    Make a delegate to handle your cross thread operation. Example:

    Code:
    public delegate void AddToTextCrossThreadDelegate(string textoadd);
    
    public void AddToText(string textoadd)
    {
        if (this.txtStatus.InvokeRequired)
            this.txtStatus.BeginInvoke(new AddToTextCrossThreadDelegate(this.AddToText), textoadd);
        else
            this.txtStatus.Text += ("\r\n" + textoadd);
    }
    This doesn't seem to work. I put a messagebox in the invoke required to see it gets called but it doesn't. I'm on a different class too. I did:
    Code:
    frmMain frm = new frmMain();
    frm.AddToText("Test");
    Last edited by Mastermosley; 03-09-2009 at 06:00 PM.

  7. #7
    Registered User
    Join Date
    Mar 2009
    Location
    england
    Posts
    209
    It's still throwing a cross-threading exception? Or am I missing the point of what the problem is here?

    If you're creating the server object in your form class, and then you're trying to access the form's textbox from the server object, then you need to use an event. However, even if this is the case, you will still need to invoke the textbox as you're accessing it from a child thread!

    Here's a little demo I made for you to explain what I mean. Ok so I made a form and dropped a TextBox onto it, and then added a Load event to the Form. I then made an object called MyServer:

    Code:
    using System;
    using System.Threading;
    
    namespace WindowsApplication13
    {
        class MyServer
        {
            public delegate void MyLoggingDelegate(String text);
            public event MyLoggingDelegate OnLogTextAdding;
    
            private Thread my_thread;
    
            public void Start()
            {
                this.my_thread = new Thread(new ThreadStart(this.ThreadWorker));
                this.my_thread.Start();
            }
    
            private void ThreadWorker()
            {
                while (true) // send test message every 1 second
                {
                    OnLogTextAdding("this is a test message!");
                    Thread.Sleep(1000);
                }
            }
        }
    }
    It's not a real server, but when Start() is executed it will try to send a test message back to the form's textbox every 1 second.

    Add this code to the form:

    Code:
    using System;
    using System.Windows.Forms;
    
    namespace WindowsApplication13
    {
        public partial class Form1 : Form
        {
            private MyServer my_server;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                this.my_server = new MyServer();
                this.my_server.OnLogTextAdding += new MyServer.MyLoggingDelegate(this.OnLogTextAdding);
                this.my_server.Start();
            }
    
            private void OnLogTextAdding(String text)
            {
                if (this.textBox1.InvokeRequired) // are we cross threading?
                {
                    this.textBox1.BeginInvoke(new MyServer.MyLoggingDelegate(this.OnLogTextAdding), text);
                }
                else
                {
                    this.textBox1.Text += (text + "\r\n"); // add new text plus line break
                    this.textBox1.SelectionStart = this.textBox1.Text.Length; // stop the new text being highlighted
                    this.textBox1.ScrollToCaret(); // keep it scrolled down
                }
            }
        }
    }
    Last edited by theoobe; 03-09-2009 at 06:55 PM. Reason: Added an example

  8. #8
    Registered User
    Join Date
    Mar 2009
    Posts
    23
    I'm not getting any errors, the if invoke required does not seem to be doing anything. When I call the function nothing happens. Also when I push the start button it creates a thread and calls the procedure ServerStart which is located in a different file and different class. And the function AddToText is located in the form class. Its works when the AddToText function is called from a different thread in the same class, but just doesnt display anything when called from a different class and file. Also when I try to follow your code I add an event

    public event AddToTextCrossThreadDelegate AddToText;

    and it warns me that the event is never used.
    Last edited by Mastermosley; 03-09-2009 at 07:59 PM.

  9. #9
    Registered User
    Join Date
    Mar 2009
    Posts
    23
    Also when I call the procedure from a diffrent class but the same thread nothing appears in box.

  10. #10
    Registered User
    Join Date
    Mar 2009
    Posts
    23
    Okay forget the Threading Problem, I think I found the problem and that lies in the fact that the textbox won't change at all whether or not on a different thread.

    I have the function AddToText which is located in the Form1 Partial Class

    Code:
    public void AddToText(string text)
    {
    this.txtStatus.Text = this.txtStatus.Text + "\r\n";
    }
    I want to call this from a different class so I do:
    Code:
    Form1 frm = new Form1();
    frm.AddToText("Test");
    I click a button called start and it calls the procedure on a different class and runs the code above. But nothing appears in my textbox. It works when I call it from the Partial Class Though.

    WTF?

  11. #11
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    Are you sure you are working with the same form. Cause in that case you are creating a new instance of form1.
    Woop?

  12. #12
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    477
    Quote Originally Posted by Mastermosley View Post
    Okay forget the Threading Problem, I think I found the problem and that lies in the fact that the textbox won't change at all whether or not on a different thread.

    I have the function AddToText which is located in the Form1 Partial Class

    Code:
    public void AddToText(string text)
    {
    this.txtStatus.Text = this.txtStatus.Text + "\r\n";
    }
    I want to call this from a different class so I do:
    Code:
    Form1 frm = new Form1();
    frm.AddToText("Test");
    I click a button called start and it calls the procedure on a different class and runs the code above. But nothing appears in my textbox. It works when I call it from the Partial Class Though.

    WTF?
    Obviously, nothing happens, because your function is adding the text in the textbox to the text in the textbox.

    Change
    Code:
    public void AddToText(string text)
    {
    this.txtStatus.Text = this.txtStatus.Text + "\r\n";
    }
    to
    Code:
    public void AddToText(string text)
    {
    this.txtStatus.Text = text + "\r\n";
    }
    "What's up, Doc?"
    "'Up' is a relative concept. It has no intrinsic value."

  13. #13
    Registered User
    Join Date
    Mar 2009
    Posts
    23
    No thats what I wanted, I was using the text box to hold multiline status I just forgot to add text but thats not the problem. The problem was i was creating a new form which was invisible, I added a static reference in the Program Class for Form1 and now it works.

  14. #14
    Registered User valaris's Avatar
    Join Date
    Jun 2008
    Location
    RING 0
    Posts
    507
    You need to call Show() or ShowDialog() on your form to display it.

Popular pages Recent additions subscribe to a feed