I am completely new to WPF.
I am writing a simple ui for patient monitoring. In the main screen, I have 3 beds i.e. 3 Buttons
I want to run some background process which basically change the background color of each of the button based on some condition. Each button will have its own process before it updates the color.
Multithreading is a large beast to tackle and even more difficult to debug if you don't fully understand the characteristics of multi threaded environments. Be careful of deadlocks, inadvertently overwriting data in a different thread, and race conditions. With this said I would suggests 2 things to first explore when writing multithreaded applications.
background workers and async functions.
I would start with the background worker and try to send it generics and such, but keep in mind that any changes to the GUI must be done on the same thread that created the GUI (main thread). So callbacks must be in place which the on completed event of the background worker will allow you to do.
Related
I'm new to developing Winform application (using C# .NET)
My application will freeze and sometimes even showing "not responding" when there are too many operations running behind, especially when it involves a lot of data reading/writing to/from database. The application did NOT crash though, it just freeze until the all code behind were finish executing.
My question is, how do I "unfreeze" the application. For example, the user can still click the "cancel" button to terminate whatever the operation is running, or show a progress bar or something like that?
Your application freezes because it has single thread, which is responsible both for drawing UI and doing other 'heavy' operations (reading/writing to database). When thread is busy with database, it cannot refresh UI. You should perform 'heavy' operations in background thread(s). Thus main thread will be responsible only for refreshing UI and it will be always ready to do that. Use BackgroundWorker component to run some operations on background threads.
Suggested reading: BackgroundWorker Class Sample for Beginners and How to: Use a Background Worker
A windows application will stop working if you are using a System.Timers.Timer.
To fix this, change System.Timers.Timer by System.Windows.Forms.Timer
Greetings
I have to render about 10'000 wpf controls, and I don't want to freeze my application during this action. Is it possible to do it in another thread?
I tried to use
myStackPanel.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.SystemIdle,
new NextPrimeDelegate(this.AddButton));
and another variants of Dispatcher. But it always freeze my application. I'd like to show animated waiting screen during creating hundred controls, but it's always freeze, because it's dispatcher's thread.
thanks for help
Andrew.
WPF controls must be created on the thread associated with the dispatcher where they will be presented. The call to Dispatcher.BeginInvoke schedules the specified action to run on the dispatcher thread at a later time, not on a background thread.
If you have a lot of UI controls to create and want to display an animation during their creation, then you will need to segment the work to be done into small units that can be quickly processed. You can then call BeginInvoke at a priority lower than normal to process each unit of work group individually.
The fact that you need to create 10,000 controls is extreme and you should probably investigate virtualizing the controls.
In my Silverlight application, I have an operation that takes a couple seconds and strongly interacts with the GUI (creation of display objects in a big "for" statement)
At first I thought of using the BackgroundWorker to avoid freezing the interface. But I cannot update the GUI directly, so I used the Dispatcher.BeginInvoke, but it still freezes the interface (since the long actions are on the gui part).
What I'd want is display a BusyIndicator while it loads my objects but I want the user to be able to continue working while it loads.
What else can I do? Any suggestions?
Even a busy icon won't help you here. Busy icons, or any other graphics item, require the UI thread to pump messages in order to not "freeze" the UI. If your long running operations are running on the UI thread then even the busy cursor will "freeze".
You need to either
Move the expensive long running logic to a background thread
Break up the UI logic into chunks and let the UI refresh in between them.
Creating UI items in the BackgroundWorker is just wrong. Creating UI elements requires switching back to the UI thread if run from a BackgroundWorker. That is just making things worse than creating them on the main thread.
I assume that lots of the work in the BackgroundWorker is not creating the elements but some additional processing that happens to create UI elements in the middle of everything else.
If that is the case you need to break out the actual generation of UI elements. Replace the generation of UI elements with dummy-classes that contains all specifications required to build all elements. Then you return that collection of specifications (the dummy-classes) and generate the actual elements in the BackgroundWorker.RunWorkerCompleted event.
My program consists of a large graphing UI control that I need to spend about 15 seconds re-loading every once in a while. Because the updating code works primarily with the UI control (maybe 90% of it actually sets properties on the control), it would make sense to me to actually let the UI thread handle that. I really don't want the control to visually re-paint while it is loading in a separate thread from the UI.
I also want a progress bar to update as well that lives in the status bar of the same application window. Is there a way to break the rule in this case and re-paint only the progress bar, or should I just open a new application window for the progress bar to live in?
What would you do in this particular case?
If you can break your primary task (ie. updating the graph) in many steps, you can perform each step as a separate dispatcher message. This will allow other messages to be processed, including giving you the ability to update progress information.
The basic pattern is:
Invoke your primary task, passing in zero for the step.
Perform the step.
If there are more steps, queue another message, passing in step + 1.
You can then add in progress updates at the appropriate points in your code.
PS. Not saying this is your best option - hard to tell without knowing all the details. But this is an option.
It is not really true that there is only one UI thread in an application, it is just that most windows applications only ever create UI objects in one thread so this thread becomes "the" UI thread in the application. It is easy to understand why - this makes the code simpler to understand, and protects us from implicit thread binding issues between controls.
This suggests a possible idea, should it prove impossible to improve the speed of updating the control (which is what I would suggest to do first). Create the UI control on a separate thread. You need to make sure that the thread is suitable for UI, that is to say the threading model is STA, and that it will pump messages and not die before the control is destroyed. I don't know if you need to create the parent window in the UI thread as well, or just the control but it may be worth experimenting here.
Find a graphing UI control that is more efficient. Unless the UI thread yields to the message loop any other updates won't happen (and it will slow down your graph control's updates).
I would suggest using a progressbar in a new window (without the form headers). Make it paint the progress bar by reading the shared properties of a graph control. this way you can avoid the thread blocking (sluggish loading).. And it gives you good visual experience (progressive painting on both the controls).
I'm looking at creating a tabbed interface which has user controls (possibly written by plug-in developers) within a tabbed or MDI interface. These plug-in controls could unintentionally freeze their GUI thread, and I'd prefer that they not influence user controls in other tabs. Much like Google Chrome creates a process for each tab; but in this case, just threads.
Or perhaps even an MDI interface where the child MDI forms are owned by separate threads?
I've found that while I can run multiple GUI threads at once, the Form level is where they MUST be separated. Any workarounds/ideas?
For those saying this shouldn't be needed, I call bullshit. Google's Chrome browser runs tabs in separate processes for security and UI reasons. I'm merely trying to duplicate this behavior. When the people writing the user controls are sucky plug-in developers, this is important.
No it is not possible to do this in the way you are describing. A control which is owned / affinitized to another GUI thread cannot be directly contained within a control which is owned / affinitized to a different thread in such a way that it's paint function runs on the other thread.
The right way to fix this situation is to write UserControls that don't perform long-running tasks on the UI thread. If the control is blocking and waiting on some computational task, fix that. Make that task run in the background, and have the control display some non-compute-intensive content until it's done. If that task freezes, the control will be frozen in its "I'm waiting..." state, but it won't intrude on the rest of the UI.
If you're using a third-party control that you can't fix, well, in the immortal words of Jay-Z, I feel bad for you, son.
For the most part, controls shouldn't be performing any processing. Their purpose is to provide interactivity between the user and the application. For example, it is not the job of a button to fetch data from a database and present it to the user. That being said, hopefully you are doing your processing in a controls event handler, such as the Click event on the Button control. In your event handler, you can prevent the UI from appearing "hung" by processing tasks in a background thread. The BackgroundWorker is often useful in these situations.
I suggest reading up on Threading. The Microsoft® .NET Framework Application Development Foundation book has a section on threading (even if no other certification books are read, I at least recommend all .NET developers read this book). Just remember not to update the UI from a child thread. Read an example on how to make a thread-safe call to Windows controls if you're not familiar with this approach.
Instead of having or owning different GUI threads, you should view the whole issue from a different angle. Why would you want a thread associated to tab's child control to be freezed? If it does freeze and everything else feezes too, threading aside, that's not done right from ground up.
What JaredPar pointed out is correct, but that doesn't mean you cannot achieve what you want. I assume you want stuff running within a tab to continue running/stopping without affecting other controls and user-experience.
I've done it before in a complex WinForm app. Here are some readings which might give you more insights:
Threading out tasks in a C#.NET GUI
Thread and GUI
Updating GUI from Other Threads in C#
Advanced Techniques To Avoid And Detect Deadlocks In .NET Apps