Accessing an object from another thread

I have a Server class that basically expects a connection from a client. Inside this class, I create a NetworkStream object to be able to receive bytes from the client. Since the NetworkStream.Read () method is not asynchronous (this means that it will wait until it reads bytes from the client to continue executing code similar to the Messagebox method), I have to read the bytes in a separate stream so that the user using the program , It can still interact with the program if the program expects to wait for data to be read.

in any case, many objects belong to this stream. One example is that I have a list called a journal in this class. I use this list to find out the status of the server. Perhaps he is listening for a connection, or perhaps the status is “connected” or “disconnected”.

So, if I do something like:

Server myServer = new Server("192.168.0.120","1300"...\\ I pass the appropite parameters in order to instantiate it //... .. then I am able to latter look at the log as string foo = myServer.Log[0] for example. 

because I want to know when the log is updated, in the server class I created an event like:

  public delegate void onUpdateHandler(string newStatus); public event onUpdateHandler onUpdate = delegate { }; 

Then I fire events in the Server class as:

  onUpdate("waitingForConnection"); 

and I get these events using the method:

enter image description here

but if I try to do something using newStatus, I get an error:

 System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it. 

so how can i pass an object with an event?


Edit

therefore, I also notice that if:

enter image description here

I also get an error message!

but when I do the same, calling it a button:

  // SERVER IS RUNNING BEFORE CALLING THIS METHOD private void button3_Click(object sender, RoutedEventArgs e) { listView1.Items.Add("my own string"); } 

I am NOT getting an error message!

why I get an error message with an event, and I don't get an error when called with a regular button.

+7
source share
2 answers

The problem is that the stream is trying to access the ListView, which is a DependencyObject that is associated with the stream, use Dispatcher to execute such methods in the user interface, for example:

 Application.Current.Dispatcher.Invoke((Action)(() => { listView1.Items.Add(newStatus); })); 

Also see the stream model description link for more information.

+12
source

The problem is not that you are trying to do something with the value that you sent to the method, the problem is that you are trying to do with it.

The event handler still works in the background thread, and from there you cannot use the user interface controls, since they relate to the main thread.

The usual processing method is to use the CheckAccess method to verify that the runs need to be switched and the Invoke method to transfer work to the main thread:

 void server_onUpdate(string newStatus) { if (!listView1.Dispatcher.CheckAccess()) { listView1.Dispatcher.Invoke(server_onUpdate, newStatus) } else { listView1.Items.Add(newStatus); } } 
+1
source

All Articles