Search code examples
c#wpfxamlbusyindicator

How to force BusyIndicator?


I use Extended WPF Toolkit BusyIndicator

My Xaml

<extToolkit:BusyIndicator Name="wait" IsBusy="False" Cursor="Wait" Grid.ColumnSpan="3" Margin="10,10,10,10"/>

My code:

private void esp_Click(object sender, RoutedEventArgs e)
{
    wait.IsBusy = true;

    // My work here make some time to finish

    wait.IsBusy = false;
}

But it never be showed, I try to make MessageBox in the end of the function the BusyIndicator be showed after the MessageBox,

I tried

wait.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Send,
                       (Action)delegate
{
    wait.IsBusy = true;
});

But I got nothing!!! Where’s the problem here I can’t resolved it?

I found a similar question but I don't have the same problem the indicator showing up but after the complete of the function.


Solution

  • The problem is that you're performing all the work in dispatcher's thread (I assume that esp_Click is an event handler). This effectively means that while performing long tasks, UI is not being updated.

    You need to perform work in separate thread - either create a new thread, use thread pool or create a task. Set IsBusy to true before starting and to false after completing your work. You'll need to use Dispatcher.BeginInvoke/Invoke when updating wait.IsBusy from another thread.

    Sample code:

    private void LongRunningTask() 
    {
       // your long running code
    
       // after you complete:
       Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Send,
                               (Action)delegate
        {
            wait.IsBusy = false;
        }); 
    }
    
    private void esp_Click(object sender, RoutedEventArgs e)
    {
       wait.IsBusy = true; // either here, or in your long running task - but then remember to use dispatcher
    
       var thread = new Thread(LongRunningTask);
       thread.Start();
    
       // OR
    
       ThreadPool.QueueUserWorkItem(state => LongRunningState());
    
       // OR, in .NET 4.0
    
       Task.Factory.StartNew(LongRunningTask);
    }
    

    Note that neither of this solutions handles exceptions - you'll have to add error handling yourself (or use task continuations in case of last sample).