Delegates And Cross Thread Exception - c#

Whenever i am updating UI in windows form using delegate it gives me cross thread exception
why it is happening like this?
is there new thread started for each delegate call ?
void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//this call delegate to display data
clsConnect(statusMsg);
}
protected void displayResponse(string resp)
{
//here cross thread exception occur if directly set to lblMsgResp.Text="Test";
if (lblMsgResp.InvokeRequired)
{
lblMsgResp.Invoke(new MethodInvoker(delegate { lblMsgResp.Text = resp; }));
}
}

The DataReceived event is always raised on a threadpool thread. You cannot update any UI control, you have to use Control.BeginInvoke(). There is no point testing InvokeRequired, it is always true.
A couple of things to keep in mind here:
Don't call Control.BeginInvoke for every single character or byte that you receive. That will bring the UI thread to its knees. Buffer the data you get from the serial port until you've got a complete response. Using SerialPort.ReadLine() usually works well, a lot of devices send strings that are terminated by a line feed (SerialPort.NewLine).
Shutting down your program can be difficult. You have to make sure to keep the form alive until the serial port stops sending. Getting an event after the form is closed will generate an ObjectDisposed exception. Use the FormClosing event to close the serial port and start a one second timer. Only really close the form when the timer expires.
Avoid using Control.Invoke instead of BeginInvoke. It can deadlock your program when you call SerialPort.Close().
Lots of ways to get in trouble. Consider using your own thread instead using DataReceived to avoid them.

Port_DataReceived is obviously an async event handler that is being raised by a thread on port monitoring component.
is there new thread started for each
delegate call ?
No, probably not. Your port monitoring component is running the poll on a background thread and the event is being raised from that thread, every time.
The point is that it is being called on a thread other than the UI, so you will need to use Control.Invoke and the patterns associated with it.
Consider this, (and read the post that may illuminate things for you)
void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//this call delegate to display data
UpdateTheUI(statusMsg);
}
private void UpdateTheUI(string statusMsg)
{
if (lblMsgResp.InvokeRequired)
{
lblMsgResp.BeginInvoke(new MethodInvoker(UpdateTheUI,statusMsg));
}
else
{
clsConnect(statusMsg);
}
}
With all of that said, I would be remiss if I didn't point out that the indirection is troubling.

Cross Thread exception happens when some none UI thread changes UI elements. Since UI elements should be changed only in the UI thread this exception is thrown. To help you understand why this happen you will have to publish you code.

Cross thread exception happens when some none UI thread changes the UI elements. To fix this use the Invoke method on the control itself. As an extra you can check InvokeRequired on the control before calling the Invoke method
See msdn

Related

How to wait for serial port to empty before closing

I have a serial port receiving data from an embedded device asynchronously. The user has the option to terminate the connection with the port at any time but this means that I get an exception if the user disconnects mid-transmission (sometimes the program just halts on myPort.Close()). Is there a way I can add a 'wait until empty' command? Something like this below?
private void tsDisconnect_Click(object sender, EventArgs e)
{
try
{
while(myPort.BytesToRead > 0)
{//wait here}
}
myPort.Close();
}
Waiting doesn't fix the deadlock you get from calling Close(), you'll need to fix the core problem. It is almost always caused by the code in your DataReceived event handler. We cannot see it, but a very common mistake is to use Control.Invoke() or Dispatcher.Invoke().
A serial port cannot close until the event handler returns. But it can't return because it is stuck in the Invoke() call. Which cannot complete because your UI thread is busy, it is stuck in the Close() call. Or is waiting for BytesToRead to get to 0, the solution you are pursuing. Won't work either, your DataReceived event handler is stuck and not reading anymore. Deadlock city.
You'll need to fix that code and use BeginInvoke() instead. That's a non-blocking call, it can't cause deadlock.
There are other possible reasons for deadlock. Easy to diagnose, you've got lots of time to debug it :) Use Debug + Break All, then Debug + Windows + Threads. Double-click the Main thread and look at its call stack to see what the UI thread is doing.

Thread calling problems

I'm a bit of a newbie at this but I am trying to get the UI on a Reversi game to run on a different thread to the move selection part but I am having some trouble calling the thread on the button click
private void playerMoveOKButton_Click(object sender, EventArgs e)
{
ReversiT.Invoke();
}
public void ReversiT() {...}
If you're trying to create a new thread, you can do something like this:
Thread thread = new Thread(ReversiT);
thread.Start();
Invoke is used for a different purpose though. It is used to run a method on a specific thread (for instance, if you run a piece of code on a separate thread but want to make UI changes, you will want to use Invoke to make those changes on the UI thread)
I would create a BackgroundWorker to handle everything for me, setting it's DoWork event to call your move method (making sure that your move method doesn't touch the UI, or if it has to, invoking the controls on the UI thread).
I'd also set up a method to update the UI on the BackgroundWorker's RunWorkerCompleted event.
Now on your button click event above, call the BGW's RunWorkerAsync() method.
You can not invoke a method like that. You can only invoke delegates. Also, calling Invoke doesn't spawn a new thread.
You can read this tutorial about delegates, and this one about threads. Also, your question leaves much space for discussion:
What do you expect from using threads?
Have you considered different options for doing background work?
etc.
Use following
this.Invoke(ReversiT);
I think you need to think about that you are actually trying to achieve here. Running code on a separate thread in a UI is a technique used to stop the UI from hanging. However, some tasks simply have to occur on the UI thread and so can't be run from another thread.
You need to break your logic out such that you can identify which parts need to run on the UI thread (anything that interacts with a control on your UI) and thus anything that can run on a separate thread.
You would end up with code like (as an example):
private void playerMoveOKButton_Click(object sender, EventArgs e)
{
//thread is merely used as an example
//you could also use a BackgroundWorker or a task
var thread = new Thread(NonUiLogic);
thread.Start();
}
private void NonUiLogic()
{
...
//execute logic that doesn't touch UI
...
BeginInvoke(ReversiT);
}
public void ReversiT() {...}
Once you have been through that exercise you may find that there is actually very little that can happen outside of the UI thread and so you really have nothing to gain from using threads.

Form UI Freeezes even after using Backgroundworker when using Flickr.Net API

Im trying to upload some images using the Flickr.net API.The Images are uploaded but the User Interface freezes.I have inserted the code for uploading in a Background worker
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
foreach (var item in imagelist)
{
flickr.UploadPicture(item, Path.GetFileName(item), null, null, true, false, true);
}
MessageBox.Show("Success");
}
The flickr object is created earlier from another form and passed to this form. I call the worker with if(worker.IsBusy==false){backgroundWorker1.RunWorkerAsync();} when a button is clicked.
Two common causes for this, your snippet is way too brief to narrow down which it might be. First is the ReportProgress method, the event handler runs on the UI thread. If you call it too often then the UI thread can get flooded with invoke requests and spend too much time to handle them. It doesn't get around to doing its regular duties anymore, like responding to paint requests and processing user input. Because as soon as it is done handling a invoke request, there's another one waiting to get dispatched. The UI thread isn't actually frozen, it just looks like it is. The net effect is the same. You'll need to fix it by slowing down the worker or call ReportProgress less often.
The second cause is your flicker object not being thread-safe and itself ensuring that it is used in a thread-safe way. By marshaling the call from the worker thread to the UI thread automatically. This is very common for COM components, this kind of marshaling is a core feature of COM. Again the UI thread isn't actually frozen, but it still won't handle paint and input since it is busy uploading a photo. You'll need to fix it by creating the flicker object on the worker thread. With good odds that you can't do this with a BackgroundWorker, such a component often needs an STA thread that pumps a message loop. Which requires Thread.SetApartmentState() and Application.Run().
If you are doing something like:
while(worker.IsBusy)
{
}
to wait for it to finish, this will hang because it ties up the UI thread in the loop and since the background worker needs to invoke onto the UI thread to set the busy property safely there is a dead lock.

what is the best way to handle potential non thread safe events

please consider the following scenario for .net 2.0:
I have an event that is fired on system.Timers.Timer object. The subscriber then adds an item to a Windows.Forms.Listbox upon receiving the event. This results in a cross-thread exception.
My question is what would be the best way to handle this sort of situation. The solutions that I have come up with is as follows:
private delegate void messageDel(string text);
private void ThreadSafeMsg(string text)
{
if (this.InvokeRequired)
{
messageDel d = new messageDel(ThreadSafeMsg);
this.Invoke(d, new object[] { text });
}
else
{
listBox1.Items.Add(text);
listBox1.Update();
}
}
// event
void Instance_Message(string text)
{
ThreadSafeMsg(text);
}
Is this the optimum way to handle this in .net 2? What about .net 3.5?
There's no point in using Control.InvokeRequired, you know that it always is. The Elapsed event is raised on a threadpool thread, never the UI thread.
Which makes it kinda pointless to use a System.Timers.Timer, just use the System.Windows.Forms.Timer. No need to monkey with Control.Begin/Invoke, you can't crash your program with an ObjectDisposedException when the event is raised just as the user closes the form.
You have a cross thread exception because you are trying to access items from outside the UI thread. Delegates are necessary in order to hook into the message pump and make the UI change.
If you use the Form Timer, then you'll be in the UI thread. You'll have the same problem, however, if you use a BackgroundWorkerThread and you'll need a delegate there as well.
See Threading in Windows Forms
It is pretty much the same in .net 3.5, since it is related to Windows Forms and cross-threading when you are accessing the UI thread from some another working thread.
However, you can make the code smaller, by using the generic Action<> and Func<>, avoiding creating manually the delegates.
Something like this:
private void ThreadSafeMsg(string text)
{
if (this.InvokeRequired)
this.Invoke(new Action<string>(ThreadSafeMsg), new object[] { text });
else
{
// Stuff...
}
}
The easiest solution in your case - is using System.Windows.Forms.Timer class, but in general case you may use following solution to access you GUI-stuff from non-GUI thread (this solution applicable for .net 2.0 but it more elegant for .net 3.5):
public static class ControlExtentions
{
public static void InvokeIfNeeded(this Control control, Action doit)
{
if (control.InvokeRequired)
control.Invoke(doit);
else
doit();
}
}
And you may use it like this no mater from what thread, from UI or from another one:
this.InvokeIfNeeded(()=>
{
listBox1.Items.Add(text);
listBox1.Update();
});
Depending upon what your action is doing, Control.BeginInvoke may be better than Control.Invoke. Control.Invoke will wait for the UI thread to process your message before it returns. If the UI thread is blocked, it will wait forever. Control.BeginInvoke will enqueue a message for the UI thread and return immediately. Because there's no way to avoid an exception if a control gets disposed immediately before you try to BeginInvoke it, you need to catch (possibly swallow) the exception (I think it may be either ObjectDisposedException or IllegalOperationException depending upon timing). You also need to set a flag or counter when you're about to post a message and clear or decrement it in the message handler (probably use Threading.Interlocked.Increment/Decrement), to ensure that you don't enqueue an excessive number of messages while the UI thread is blocked.

How can I tell if a thread is finished executing without polling ThreadState?

Is there an elegant way to know when a worker thread is done executing so I can access resources it produced?
For example if the worker thread queried a list of SQL Servers using
ServersSqlDataSourceEnumerator.Instance.GetDataSources();
and saved the result in a DataTable variable, what mechanism can I use to know when this DataTable variable has been populated/is available. I don't want to poll ThreadState; it would be ideal to fire an event when it's done so I can perform actions with the result.
Thanks!
You can use a callback mechanism or block on an event to know of completion of an Async operation. See this page for the Asychronous Programming Model in .net - you can call BeginInvoke on any delegate to perform the action in an Async manner.
If you're using the BackgroundWorker type, you can subscribe to the RunWorkerCompleted event.
So fire an event :-P
You could also look at using an AutoResetEvent:
http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx
What I do in this instance is get the WorkerThread to call a function after it has completed the work, which will invoke the the UI Thread, which can do the work in which you require.
E.g.
private void SetWorkerThreadToDoWork()
{
WorkerThread.Start();
}
private void MyWorkerThreadWork()
{
//This will be on the WorkerThread (called from WorkerThread.Start())
DoWorkFunc();
WorkComplete();
}
private void WorkComplete()
{
if(InvokeRequired == true)
{
//Do the invoke
}
else
{
//Check work done by worker thread
//e.g. ServersSqlDataSourceEnumerator.Instance.GetDataSources();
}
}
If it's a simple process you're using, I'd go for a BackgroundWorkerThread, this comes with it's own events that are fired when work is complete. But if you require to use a Thread, I would either look in to Asynchronous Callbacks or a similar route to that shown above.
You can check my answer on this SO thread
It uses a call back mechanism. When the async operation is done, it will fire the callback method where you can handle the processing that needs to be done post SQL execution.
Use a similar approach to be notified when the asynchronous operation is done.
Hope this helps :)
I don't program in C# but here's what I did with Delphi, maybe you can do it as well with C#.
I have a TThread descendant, and in the "destroy" event I send a message to its creator saying "hey I'm about to die !".
This way its parent (which is the main thread) creates a new one if it needs a new one. To be precise it launches a timer that, when fired, creates a new thread if a new one is needed (sites sucking time (lol) !!).

Categories

Resources