Refresh Page while doing intense backup processing

Wizard for WPF Forum

Posted 15 years ago by Anurodh Ora
Avatar
Hi,

We have following requirement.

1) We have two pages say Page1 and Page2.
2) We get user input from Page1 and then click Next to go on Page2.
3) Page2 has some labels with content "Step #(Number of step) Succeeded" initially grayed out.
4) As soon as we click on Page1 Next button we should get into an intense background function which talks to server for number of times times and each time a step succeeds it should show page2 with that particular step label changed to black color.
5) Application should be blocked till the function exits.

For above scenario. We are doing following things.
1) Check on page selection changed event if new page is Page2 we call a function say IntenseWorkerFunction() (which typically refreshes Page2 label contents when a server step succeeds like label1.Foreground = Brushes.Black;)
2) Calling Dispatcher.BeginInvoke() to update UI of Page2.

Problem:
1) After clicking on Next on Page1 the application hangs (Page2 do not get showed up)
2) After all the server functionality gets over, that is IntenseWorkerFunction() finishes then only Page2 shows up.
3) In the function we need to validate controls value of earlier wizard pages. using background thread we need to call Dispatcher.Invoke (as background thread do not get access to UI thread elements) and there are various controls which are used so performance is also an issue. So how to get values from wizard pages in BackGroundWorker is also a question.
4) Avoiding BackgroundWorker and just updating UI using Dispatcher.BeginInvoke() also did not work as the Page2 is shown only when all the processing of IntenseWorkerFunction() gets completed.
To summarize we need following:
On Page1 Next click call a sync function to process user inputs provided on Page1 and update UI of Page2 simultaneously with each user input verification from server(that takes time). How to achieve this efficiently without using BackgroundWorker class.

Note : Using Dispatcher.BeginInvoke() to update Page2 UI did not work, as Page2 only shows up when all the operations are done.

Thanks and Regards,
Anurodh

[Modified at 11/21/2008 02:20 AM]

[Modified at 11/21/2008 05:51 AM]

[Modified at 11/21/2008 06:15 AM]

[Modified at 11/21/2008 06:20 AM]

[Modified at 11/21/2008 06:43 AM]

[Modified at 11/21/2008 06:50 AM]

[Modified at 11/21/2008 07:19 AM]

[Modified at 11/23/2008 06:34 AM]

Comments (4)

Posted 15 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Anurodh,

Time-consuming processing, if done in a BackgroundWorker properly should never affect the UI. It sounds like you are definitely blocking the UI somehow in your design if you are using a BackgroundWorker yet it still doesn't show up.

In our MainControl.xaml.cs file within the Features demo of Wizard, change this method like so.
private void wizard_SelectedPageChanged(object sender, WizardSelectedPageChangeEventArgs e) {
    if (e.NewSelectedPage == processingPage) {
        // Clear the processing amount
        progressBar.Value = 0;

        // START PROCESSING
        startProcessingButton_Click(this, new RoutedEventArgs());
    }
    if (e.NewSelectedPage == cancelSelectionChangePage) {
        // Update the selection flags TextBlock to indicate what flags were used in selecting this page
        selectionFlagsTextBlock.Text = e.SelectionFlags.ToString();
    }
}
It's ugly but all we do here is call the startProcessingButton_Click to manually kick off processing on the processing sample page. When you step through the Wizard at runtime and get to the processing page, you'll see it kick off the processing and still update the UI fine.

Also note that our simpleProcessingBackgroundWorker.RunWorkerAsync(); call doesn't pass an argument however there is an overload for that which does let you pass info to the worker thread via the event args of the various worker events.


Actipro Software Support

Posted 15 years ago by Anurodh Ora
Avatar
Thanks for the reply,

But the real problem is to get values of control of previous page for validation in case we use BackGrounWorker thread like doing this in the sample application crashes it :

for (int index = 0; index <= 10; index++)
{
    Thread.Sleep(100);
    if (progressBar.Value > 50)
    {
       simpleProcessingBackgroundWorker.ReportProgress(index * 10);
    }
}
can you suggest what should we do in such a case? One is to check access if current thread owns it else call Dispatcher.Invoke (not BeginInvoke as we need the value to proceed) but then doing it for so many controls hangs the application. Can you suggest any smarter way using wizard classes ?

Because of above reason we were thinking of not to get into Background process instead there should be a way that we call a function (not background function) validate control's value , do some processing and simultaneously update UI.

How we should go about this.

Thanks,
Anurodh

[Modified at 11/22/2008 03:13 AM]

[Modified at 11/22/2008 05:17 AM]

[Modified at 11/23/2008 06:34 AM]
Posted 15 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Anurodh,

You'll probably want to do more in depth looking at BackgroundWorker on the MSDN or various blog sites so you understand what you can and can't do with it.

For instance, you can't access UI controls from within BackgroundWorker code. You can pass an argument to it as I mentioned in my previous post. So build an object that contains whatever data the BackgroundWorker needs and pass it there. That object will be available to you in DoWork.

Then a ReportProgress overload lets you pass information back to the main UI thread, which you can handle in events like ProgressChanged.

The DoWork handler also lets you set a Result in the event args which gets passed back to RunWorkerCompleted event in the main thread.

By using those things, you can work in a separate thread fine without touching UI and pass data back and forth. But again, google for some more detailed information on using these things. Even if you find posts on using it with Windows Forms, the same concepts will apply here.


Actipro Software Support

Posted 15 years ago by Anurodh Ora
Avatar
Hi,

Thanks for the reply.

We have now finally resolved this issue. For anyone who got into such a situation, the steps to follow are:

1) Run long running process (which is freezing UI) as BackgroundWorker process
2) Collect your data that is required for long running process in a structure/class
3) Pass the object to the BackgroundWorker process and access it from eventargument of BackgroundWorker process(Object obj = e.Argument as Object):
backgroundWorker.RunWorkerAsync(objectToBePassed);
4) Call backgroundWorker.ReportProgress(int,object), you can pass object data from here to update UI based on that data.
Note: Remember to set backgroundWorker.WorkerReportsProgress = true;
5) To cancel the background process remember to set
backgroundWorker.WorkerSupportsCancellation = true;

Note: Do not check backgroundWorker.IsBusy Because, if you put GUI thread into a tight loop checking IsBusy it will never let the message pump respond to the ReportProgress.

Thanks and Regards,
Anurodh

[Modified at 11/27/2008 12:41 AM]
The latest build of this product (v24.1.2) was released 0 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.