Background work that perform UI change and modal dialog - c#

I have a C#/WPF application that is going to perform a lot of actions, including UI modifications (it is loading a Macro), but I want to have a modal window with something moving telling to wait.
The load macro work must be performed in the main application thread, but how to I print the modal window as it must be non blocked by the macro loading but in the application thread because it is a UI thing.
Currently I put the LoadMacro in an BackgroundWorker in a Application.Current.Dispatcher.Invoke while displaying my waiting dialog. But it is not satisfying because the two fight each other to update the UI.
So how do I do it ?

You don't need to run the background worker from any dispatcher.
Load your modal window and then kick off the background worker having subscribed to it's ProgressChanged event. You can then ReportProgress on the background worker passing anything you like back to update the model window in the UserState property.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.progresschanged.aspx

Related

Cross-threading error/ Unresponsive UI

I have a WPF application in which I have a MainWindow under UI thread. I have created a thread in which I create another window. I have to create this window in a thread because it has to be updated continuously. I want the owner of this window to be the MainWindow. So I am using Dispatcher.Invoke to set the owner of this window.
But when I use Dispatcher.Invoke to access Main UI Thread from Thread 2, I get a cross thread access exception.
I'll post some sample code very soon. Until then, if someone has any idea, please share it.
This is my actual problem to which I thought of implementing above mentioned approach:
I have three line charts with 4 line series each in a window which are updated at an interval of 100 ms which I am doing using Dispatcher.Invoke. Because of this, the UI becomes kind of slow and unresponsive sometimes
I have created a thread in which I create another window.
That already isn't a very good idea and is prone to a lot of problems. All windows in your application should be created by the main "GUI" thread.
I have to create this window in a thread because it has to be updated continuously.
There are ways to achieve that without creating the window on another thread. Create your window on the main thread, then use a background thread to update it. That background thread can update your new window by using Dispatcher.Invoke.

How to prevent a Not Responding message on a window's title bar?

I use VS2010 and C# to build a desktop application. This application has one form with a huge task which takes a lot of time to complete. When this form is initialized it works perfectly, except it shows “Not Responding” on the title bar, like the picture shows:
After completing all tasks, it shows the desired output. Why is this message shown, and how do I prevent it?
You need to use a BackgroundWorker so that the time consuming task will run in a separate thread asynchronously. That will allow Windows multitasking to make the UI responsive. You should use a wait cursor or some other visual indicator to let the user know that your application is busy.
From MSDN MSDN BackgroundWorker
The BackgroundWorker class allows you to run an operation on a separate, dedicated thread. Time-consuming operations like downloads and database transactions can cause your user interface (UI) to seem as though it has stopped responding while they are running. When you want a responsive UI and you are faced with long delays associated with such operations, the BackgroundWorker class provides a convenient solution.
To execute a time-consuming operation in the background, create a BackgroundWorker and listen for events that report the progress of your operation and signal when your operation is finished. You can create the BackgroundWorker programmatically or you can drag it onto your form from the Components tab of the Toolbox. If you create the BackgroundWorker in the Windows Forms Designer, it will appear in the Component Tray, and its properties will be displayed in the Properties window.
To set up for a background operation, add an event handler for the DoWork event. Call your time-consuming operation in this event handler. To start the operation, call RunWorkerAsync. To receive notifications of progress updates, handle the ProgressChanged event. To receive a notification when the operation is completed, handle the RunWorkerCompleted event.
You need to run your huge task on a background thread so as not to lock up the UI (main) thread.

Creating complex WPF-Window in Background

I have a very complex Window created with WPF.
Since it takes very long time to load (about 10s), I want to create the window in the background after startup of the application.
My Shell contains one button where this window will be used, when the User clicks on it. The idea is to load the application and this button is disabled. After loading, my complex will be created in the background. When the window is created, I can enable this button and the user can use it.
But it is very important, that the Application does not block, while the window will be created on the background. The user should be able to use other modules in this time.
Does somebody know a way to reach my goal?
Perhaps someone knows, if there are more possibilities to reach this goal in the next .NET-Framework 4.5?
You can create window in background thread. Things you need to pay attention to are:
Thread must be STA and should be background thread so it will be terminated if main application thread is terminated.
You must keep that background thread alive or you will loose your window.
When referencing other GUI elements you should use Dispatcher.Invoke or Dispatcher.BeginInvoke if that GUI element is from another thread.
Here's the example for creating window in background thread:
Thread thread = new Thread(() =>
{
Window windowInAnotherThread = new Window();
windowInAnotherThread.Show();
System.Windows.Threading.Dispatcher.Run();
}) { IsBackground = true };
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
Use the BackgroundWorker.
Note that you can not create the actual window in the BackgroundWorker. The window needs to be created on the UI thread. But you can load all necessary data in the BackgroundWorker and use that data from the form once it is loaded.

Mouse click when the application is busy

When I click on anywhere on my application when the application is busy it changes the cursor into a generic wait cursor. Is there anyway I can code it for an animated cursor?
This is because you must be doing some heavy operation on main UI thread. Do your processing in background (in separate thread).
You may use BackgroundWorker or Thread class to achieve this.
Windows will always use the generic "busy" cursor if the user tries to interact with it and your application is not responding.
The solution to this is to not do processing on the UI thread - do it on other threads, so your UI remains responsive.
If your UI is still responding, you can set a custom cursor to indicate that your application is busy processing.
if you are using the windows application in ASP.NET then there is a option realted to cursor in properties of the form(nit clearlly remember, it was like wait.cursor). You can use that to display the custom cursor at the time of processing also.

Waiting on Mainthread while continuing processing on UI

When working with console applications, Console.Readline relinquishes processing to the UI from the Main thread and only continues when an event, such as the pressing of the enter button is fired. How do I replicate this functionality (With a Window form as the UI in this case) in windows form application?
You cannot do this directly.
However, you can do it by calling Invoke, as I described here.
Use form.ShowDialog() instead of form.Show()
This will not stop the thread, but it will stop the user from doing other things in the UI until the window is closed.
Now that you have explained what you want to do...
It would be better to use a BackgroundWorker, keep the GUI active, but disabled and presenting a progress bar + cancel button, until done.

Categories