Hi

I have created a class that creates another thread. That background thread than creates a tcp client, connects to listener and waits for a message that will be send by the listener. When the message is received, it raises an event and waits for new messages. The problem is that the event is raised in background thread, instead in the thread that created that instance of my class. Does anybody has any idea how could I notify my main thread, so that thread could raise the event or if anybody has any other solution. I guess I need to implement something like Invoke method that every control has. but I don't know how I can do that. Any advice will be appreciated.

Thanks in advance

Uros

Recommended Answers

All 7 Replies

Use System.ComponentModel.BackgroundWorker class. This will provide the exact solution for your problem. There are two events init that you need to subscribe one DoWork and the other RunWorkerCompleted. The RunWorkerCompleted basically fires on the main thread.

if I understand your problem correctly you are raising an event from your background thread and it is calling a function from your main class. and you probably are getting a runtime error. the reason for that error is that your main class is getting handled by your main thread and you are calling main method's function from background method. so what you have to do is ,like you said , to use invoke method. since you can not call any function accross threads, you should send the function to the main thread and main thread will run it for you. here is some sample code. it checks if we have to use invoke method(if there is a cross thread call) and send it to other thread and call the same method if needed. any way . if you have further questions please don't hesitate to ask.

mainwriting area is a rich text box.

private void write(string str)
        {

            if (MainWritingArea.InvokeRequired)
            {
                writeOnRichBox w = new writeOnRichBox(write);
                MainWritingArea.Invoke(w, new Object[] { str });
            }
            else
            {
                MainWritingArea.Text = str + "\n" + MainWritingArea.Text;
            }
}

I forgott to send you the coe fot delegate that I used in that function. I am sending the code again here it is.

public delegate void writeOnRichBox(string str);
        private void write(string str)
        {

            if (MainWritingArea.InvokeRequired)
            {
                writeOnRichBox w = new writeOnRichBox(write);
                MainWritingArea.Invoke(w, new Object[] { str });
            }
            else
            {
                MainWritingArea.Text = str + "\n" + MainWritingArea.Text;
            }
        }

if you try to change richtextbox.text property directly you might get a cross thread reference error. instead you should call write method. if there is no cross thread reference it will just edit the text , but if there is a cross reference it will use invoke method. invoke method gets a delegate and an object array as parameter. in the main thread it calls fires delegate and sends objects list to it as parameter. in our case when we write

writeOnRichBox w = new writeOnRichBox(write);
                MainWritingArea.Invoke(w, new Object[] { str });

it will run write(str); method in the main thread.

Thanks for your reply. I think I wasn't specific enough. As I wrote I have a class that defines an event(MessageReceived). Beside that it also has a background thread in which I connect to tcp lisener and wait for incoming messages. When i receive the message(that happens in the background thread) I want to fire the MessageReceived event, but I want it to fire in the main thread. I am not actualy updating any control so i can not use the control.Invoke - I just want to raise the event in the same thread, in which the instance of my class was created.

Thanks. I got the same advice(To use background worker) from somewhere else so I guess that is the way to go. Thanks again

hello again!
first of all since you are listening your connection from the thread you will have to throw acception from your client. and your code in your backgroun thread probably will look like this

public delegate void PassMessage(string str);
            public event PassMessage MessageReceived;
            ..........
            while (true) 
            {
                if (stream.DataAvailable)
                    MessageReceived(getMessage());
           }

which will end with an error so like you have to call Message Received from the main thread like this

public delegate void PassMessage(string str);
            public event PassMessage MessageReceived;
            ..........
            while (true) 
            {
                if (stream.DataAvailable){
                    PassMessage p = new PassMessage(MessageReceived);
                    Form1.Invoke(p,new Object[] {getMessage()}
                }
            }

which does the same thing, only does it on the thread which Form1 belongs to. I don't know if this is helping you but there is also various examples about Invoke Method. you might wanna check them out too.. I needed the same functions couple days ago and google it.

Hi
The problem is in the 8th row above(Form1.Invoke(...). I can not know where my class will be used so I do not have a reference to any Form object(or any object that has the Invoke method) so this wont work. But I solved my problem with use of BackgroundWorker. Thanks for your time.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.