WPF custom BalloonTips problem with multithreading - c#

I have read other related question but i cant really get them to relate to this so I thought it were best to ask, Im pretty new to WPF and so on so please bear with me.
I am using this http://www.codeproject.com/KB/WPF/wpf_notifyicon.aspx api to work with custom WPF Windows (in particular FancyBalloon).
However, i'm coming across the following problem, I seem unable to start off BalloonTips in a separate thread ( i need this because i'm parsing emails and hence if there are 3 emails for instance, it displays the first email (that works fine), but when it comes to the second email it crashes with a TargetInvocationException , {"Specified element is already the logical child of another element. Disconnect it first."}.
Thing is, im supposedly working with the same instance and i have attempted calling it to close it before, disposing it etc but to no avail. (then again if i dispose it, i cant create another instance as apparently WPF UI components must be called from a static thread so throughout the looping of emails + displaying balloon, i am trying to use the same BalloonTip.
Any suggestions please? I am really at a loss here and i've been on it for quite a while now :/
I was wondering if there was anyone

In general, WPF controls should be accessed and updated only on the main UI thread. There are thread affinity checks all over the data binding innards that will throw an exception if you assign to a data bound property from any thread that isn't the WPF UI thread, for example.
You can either remove the UI code from your background worker thread, or make judicious use of a SynchronizationContext to invoke from your background thread snippets of code to execute on the UI thread.
If you're new to WPF or new to threading, you should keep the UI stuff out of the background threads. WPF has plenty of complexity to keep you busy without adding the additional headache of threading issues to the mix.

It seems you are adding the same UI element to multiple parent containers at the same time.
For example, if I attempt myStackPanel.Children.Add(myUIElement) concurrently in separate threads, referring to the same UI element object, this would cause the error you are seeing.
If you need the same UI elements for multiple threads, consider cloning them or moving your UI logic to the main thread.

Related

Is it possible to put a form control on its own thread?

I'm using a DataGridView and some operations that I do cause it to become unresponsive for periods of time. Normally I would put data processing in its own thread to make the form more responsive, but in this case it's the DataGridView itself that's taking so long.
This leads me to wonder whether it's possible to have the main form on one thread and the DataGridView on another thread so it doesn't prevent the main form from responding.
I completely understand that doing so is probably not 'safe' and likely opens up a can of worms that makes it hardly worth trying and I fully expect this post will be getting down votes for merely suggesting such a ridiculous idea.
Is this possible? And if so how would you go about it?
EDIT: I figured out how to fix the problem at hand. The short answer was to use a flag when setting the RowCount so CellValueNeeded() can bail out immediately. There's really more to the story and I had already been doing this partially, but that's the gist of it.
Short answer is no, because the control needs to interact with other controls (or at least the window), and they all need to be on the same thread.
Doing so seems to imply that you're doing processing on the UI thread, which itself is also a big no-no. You should run all of your major processes on their own thread, and then save the final presentation for the UI thread -- work on one thread, screen updates on another.
It is definitely possible to have multiple UI threads in a given application. However it is not possible to compose UI components from different threads onto the same Form. For a given form all of the components must be on the same thread
The best way to fix this problem is to move the data processing itself onto a separate thread. Only do the absolute minimum to update the UI from the UI thread. That should help with the responsiveness
take a look into use of virtualization in the grid.
And please give code sample to what operation is taking too long!
No, but from events fired from the dataGridView you could send a worker to perform async tasks and then update the dataGridView using the controls Invoke method from the worker thread

Refreshing Windows Forms controls between actions in a 'for' loop

I have a problem that I don't want to work with multithreaded applications since I am testing some code, and I need it single threaded.
It's updating the textbox only after it's all done. I need to somehow keep it updated all the time. Is there another way except with a second thread?
It's updating the textbox only after it's all done. I need to somehow keep it updated all the time. Is there another way expect with a second thread?
There isn't a good way to do this. The problem is, if you're executing code on the UI thread, the UI thread can't process the messages in the message pump, including the ones that way to refresh the TextBox, until your work completes.
In Windows Forms, you can force the application to process these messages by calling Application.DoEvents(), but this is really a bad, bad idea. It's much better (and safer!) to use a BackgroundWorker or some other multithreading technique to push the work into the background thread instead.
You could try the following:
// in for loop
tbxMyTextBox.Text = "New text!";
tbxMyTextBox.Refresh();
I remember having to do something similar in the past.

Processing Windows Messages in blocked UI Thread?

This is possibly related to ProgressBar updates in blocked UI thread but is a little different.
While troubleshooting a crashing WinForms control (a DevExpress treelist) a member of our team encountered an unusual situation, and I'm wondering if anyone can help us understand what's going on. English is not his first language, so I'm posting on his behalf.
Please see this screenshot from Visual Studio 2005.
Note the following points:
The main UI thread is stopped and is currently in a DevExpress control draw method.
The code shown on screen is from a point earlier in the same call-stack. This code is in the data layer and was called in response to the control's request for an image to display for the tree node. (perhaps also originating from a Paint handler)
The displayed code is from earlier in the callstack, on the main UI thread, and is currently waiting on a lock! Since remote systems can send events which are processed on background threads in the data model (i.e., data models are sync'd between client and servers), we lock to keep the data collections thread safe.
As the callstack shows, we continued to process paint messages on the UI thread, while we would expect the thread to be blocked.
This is very difficult to replicate, and I have not been able to do so using a simpler test project on my own box. When this situation arises, however, the result is that the DevExpress control's internal state can be messed up, causing the control to crash. This doesn't really seem like a bug in the control, since it was no doubt written with the assumption that these paint methods are running only on the UI thread. What we see here makes it look like the UI thread is acting like two threads.
It would seem possible that this is merely a Visual Studio bug in the presentation of the callstack, except that this whole endeavor is resulting from an effort to troubleshoot the occasional crash of the control in the released app (in which case it shows as a big red X in the UI), so it seems the problem is not isolated to the debug environment.
Alright, that was complicated, but hopefully made sense. Any ideas?
I would strongly recommend against locking the UI to wait for background processing. Consider something like multiple buffering. You can probably get this behavior fairly easily by utilizing thread-safe collections in .NET 4, but if that's not an option there are versions of those in the Parallel Extensions released prior to v4.
What about altering the synchronization scheme so that you don't need to acquire exclusive locks to read data?
In situations where you can be sure that a read will always produce consistent data even when it happens while the data is also being written, you might be able to get away with having no lock statements for getters. Otherwise there's ReaderWriterLockSlim, which permits multiple concurrent readers but still allows you to stop the presses for write operations.
It doesn't fix everything, but it does at least reduce the number of opportunities for deadlocks.
We see something similar in our project. The stack trace looks like the pump's event loop is called while the UI thread is waiting on a lock. This could happen if Monitor.enter has some special behavior when called on the UI thread. I believe this is what's happening, but I haven't found any documentation to back it up yet.
Probably has something to do with synchronization contexts :)

Invalid Cross thread Operations C#

I have a windows form with some controls on it. One of the controls is a textbox and the other one is listView. I also have a button (Upload) that uploads files based on the items selected item ListView object.
To report upload progress %, i added a progress bar that created a background worker thread that would upload the files, by contacting the server. The progress bar does not updates properly and appears unresponsive without the approach of creating background worker.
Now, while uploading files, i need to get the selection from ListView and get files based on that selection. But when i try to access "ListView" from background worker thread I get an exception: System.InvalidOperationException: Cross-thread operation not valid:
What should i do to correct this exception?
In this case your processing thread wants to access your UI thread.
Example:
private delegate void UpdateTextDelegate(object value);
private void UpdateText(object value)
{
if (this.textbox.InvokeRequired)
{
// This is a worker thread so delegate the task.
this.textbox.Invoke(new UpdateTextDelegate(this.UpdateText), value);
}
else
{
// This is the UI thread so perform the task.
this.textbox.Text = value.ToString();
}
}
Access to Windows Forms controls is not inherently thread safe. If you have two or more threads manipulating the state of a control, it is possible to force the control into an inconsistent state. Other thread-related bugs are possible as well, including race conditions and deadlocks. It is important to ensure that access to your controls is done in a thread-safe way.
The .NET Framework helps you detect when you are accessing your controls in a manner that is not thread safe. When you are running your application in the debugger, and a thread other than the one which created a control attempts to call that control, the debugger raises an InvalidOperationException with the message, "Control control name accessed from a thread other than the thread it was created on."
This exception occurs reliably during debugging and, under some circumstances, at run time. You are strongly advised to fix this problem when you see it. You might see this exception when you debug applications that you wrote with the .NET Framework prior to .NET Framework version 2.0
BackgroundWorker also uses a thread to do it's job.
Look at this
No code should touch any Control unless it's running on the UI thread. This means invoking methods (other than Control.Invoke()) and setting/retrieving properties. The best way to accomplish this is to make liberal use of Control.InvokeRequired and Control.Invoke(). For your particular case, you may want to look into using a BackgroundWorker to do your file uploading.
You cannot access controls created on one thread from another thread. This is a good thing, trust me. The BackgroundWorker class exposes a couple of events that can help you accomplish what you want, namely ProgressChanged and RunWorkerCompleted.
I wrote a detailed guide to some of the techniques to handle this on a forum I frequent. Look at the explanation under the "Classic Marshalling" header for a walkthrough of what the implementation looks like.
Usually, I use the ReportProgress method of the BackgroundWorker component to marshall elements from the background thread to the UI thread.
You can simply pass the progress (integer) value and you can as well pass complex objects (non-GUI only, so no ListViewItems or the like) to the GUI thread in this event.
The good solution would be using Control.Invoke/Control.InvokeRequired - it helps executing code in the GUI thread (thus not throwing an exception).
The bad/ugly solution would be Control.CheckForIllegalCrossThreadCalls = false.

Lock a winforms control

I need to ensure that, once the execution hits a method, the control received by this method is not changed by another thread.
Basically, I thought in something like this:
private void doSomeWork(Control control) {
lock (control) {
// do some stuff with the control...
}
}
Is this a bad idea?
Edit:
Actually, what I'm trying to do, is to ensure that the control will not disposed by another thread while I execute some of the control's methods (which, by the way, will be executed via reflection).
In a well behaving application, windows forms controls are already restricted to only one thread. If any thread tries to access a control created in a different thread, an exception will be thrown.
There is nothing wrong about your code, just know that right now it's mostly useless unless you are hacking your way through the protection (which is possible).
Usually, when you have data being created or manipulated in a working thread, the working thread will send an event to the UI thread to update the UI. In no way should a working thread updates the UI itself, it will automatically fail.
Actually Fernando, it's not a bad idea but it's not the correct way to look at locking. You need to closely read what the lock statement does in .Net:
http://msdn.microsoft.com/en-us/library/c5kehkcz(VS.80).aspx
i think that from your statement you expect the whole object to be locked, or somehow be made safe for threading, because the object iteself is used in a locked block of code. What actually happens is that block of code is locked and not allowed to be executed by two or more threads at the same time. If that block of code is the only place you're going to be operating on the control then you're ok, otherwise you'll need to do synch locks on the object itself.
Don't have a lot of experience working with threads, but, maybe I'll suggest you to start the Form Control in a new thread using an anonymous delegate:
t= new Thread(delegate() {
MyMethodToInvokeTheWinFormControl();
});
t.Start();
It depends entirely on what you mean by "not changed".
If your meaning is "any other thread cannot change this control, at all, in any way", then that's not how lock works.
A lock in this sense is not like a regular lock on a door to a house. It's more like a small yellow post-it note that says "Locked". As long as other threads read the note and abide by what it says, it should be fine, but any other thread that doesn't care about the note at all will of course not be prevented from messing with your control.
In any case, what exactly are you trying to accomplish? You should never be messing with controls from other than the main thread so the problem shouldn't exist in the first place.
Instead you should be marshalling all work on the control onto the main thread through the use of the Invoke method on the control.

Categories

Resources