Search code examples
c#controlswinui-3winui

Redraw control within a loop?


I'd like to update a ProgressBar control within a loop that performs some lengthy process, e.g. something like this for the sake of an example:

for (int p = 0; p < 100; p++)
{
   progBar.Value = p;
   // do some work here
}

But if I try this inside a method (e.g. a button click handler) the progress bar doesn't increment until the method exits, which sort of defeats the purpose of the progress bar being included in the UI.

Is there some way to get the progress bar control to repaint/redraw inside the loop so that the UI reflects its state immediately?

Maybe this is an old-fashioned approach to doing UI and there's just better ways these days? All advice appreciated.


Solution

  • Well, you can't do two things, such as running a loop and updating a ProgressBar, simultaneously on the same thread.

    The trick is to execute the loop on a background thread:

    DispatcherQueue dispatcherQueue = DispatcherQueue.GetForCurrentThread();
    await Task.Run(() =>
    {
        for (int p = 0; p < 100; p++)
        {
            Thread.Sleep(1500); // some long-running work...
            dispatcherQueue.TryEnqueue(() => progBar.Value = p);
        }
    });
    

    Or at least do the "lengthy process" on a background thread:

    for (int p = 0; p < 100; p++)
    {
        await Task.Run(() => Thread.Sleep(1500)); // some long-running work...
        progBar.Value = p;
    }