Update UI before actual execution of method

181 Views Asked by At

I want a loading indicator to start immediately before the execution of a method. The execution of the method involves the work of entity framework so I don't (can't) put that type of code in a new thread bc entity framework isn't thread safe. So basically in the method below, I want the first line to execute and have the UI update and then come back and execute the rest of the code. Any ideas?

 public async void LoadWizard()
 {
    IsLoading = true; //Need the UI to update immediately 

    //Now lets run the rest (This may take a couple seconds)
    StartWizard();
    Refresh(); 
 }

I can't do this:

 public async void LoadWizard()
 {
    IsLoading = true; //Need the UI to update immediately 

    await Task.Factory.StartNew(() =>
    {
        //Now lets run the rest (This may take a couple seconds)
        StartWizard();
        Refresh(); //Load from entityframework
    });

    //This isn't good to do entityframework in another thread. It breaks.

 }
2

There are 2 best solutions below

5
On

You can invoke empty delegate on UI dispatcher with priority set to Render, so that UI process all the queued operations with equal or higher priority than Render. (UI redraws on Render dispatcher priority)

public async void LoadWizard()
{
   IsLoading = true; //Need the UI to update immediately 

   App.Current.Dispatcher.Invoke((Action)(() => { }), DispatcherPriority.Render);

   //Now lets run the rest (This may take a couple seconds)
   StartWizard();
   Refresh(); 
}
0
On

Assuming your busy indicator visibility is bound to IsLoading property, you are doing "something" wrong in StartWizard or Refresh method. Your StartWizard and Refresh methods should only load data from your data source. You must not have any code that changes the state of UI in your loading methods. Here is some pseudocode..

public async void LoadWizard()
 {
    IsLoading = true; 

    StartWizard();
    var efData = Refresh(); 

    IsLoading = false;

    //update values of properties bound to the view
    PropertyBoundToView1 = efData.Prop1;
    PropertyBoundToView2 = efData.Prop2;
 }

public void StartWizard()
{
  //do something with data that are not bound to the view
}

public MyData Refresh()
{
   return context.Set<MyData>().FirstOrDefault();
}