Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF ProgressBar usage when using Async/Await

Tags:

c#

wpf

I have a very simple task that loads some data like so:

async Task<List<Invoice>> GetInvoices()
{
    var invoices = await Task.Run(() => db.Invoices.AsNoTracking().ToList());
    return invoices;
}

What would be the best way to use this with a progressbar? I don't need to get the percentage loaded (although that would be useful), I simply need to show/hide the progressbar at start and finish of loading data. Is there a way to create a completed or finished method perhaps?

I am very new to async/await so kid gloves please!

like image 353
user1166905 Avatar asked Dec 11 '22 03:12

user1166905


2 Answers

Assuming GetInvoices gets called in some UI event handler and there is some progress bar control called ProgressBar, it's really simple:

private async void OnButton1Click(..)
{
    ProgressBar.IsIndeterminate = true;
    var result = await GetInvoices();
    ProgressBar.IsIndeterminate = false; // Maybe hide it, too
    // TODO: Do stuff with result
}

If you want to show actual progress, take a look at Progress<T> and IProgress<T>.

like image 100
Sebastian Negraszus Avatar answered Dec 17 '22 01:12

Sebastian Negraszus


You already have what you need. To illustrate here's a simple example with tasks and using await, and ContinueWith.

using System;
using System.Threading.Tasks;
using System.Diagnostics;
public class Program
{
    public static void Main()
    {
        Task t = new Program().TestTasks();
        Console.WriteLine("hello");
        t.Wait();
    }

    public async Task TestTasks()
    {
        Stopwatch watch = Stopwatch.StartNew();
        Console.WriteLine("1." + watch.ElapsedMilliseconds);
        // await task
        int res = await TestAsync();
        Console.WriteLine("2." + watch.ElapsedMilliseconds + " " + res);
        // save task and wait on it
        Task<int> t = TestAsync();
        t.ContinueWith((r) =>
        {
            Console.WriteLine("4." + watch.ElapsedMilliseconds + " " + r.Result);
        });
        Console.WriteLine("3." + watch.ElapsedMilliseconds);
        t.Wait();
    }

    public static async Task<int> TestAsync()
    {
        await Task.Delay(TimeSpan.FromSeconds(2));
        return 42;
    }
}

This prints:

1.0
hello
2.2009 42
3.2009
4.4013 42

Note how the await leaves the method and prints "hello" in the Main method, and after (about) 2 seconds continue in the TestTasks method. On the other hand, if we do not await, as the second call to TestAsync shows, 3. is printed immediately, and after 2 seconds, 4. is printed.

With this in mind, you can just call your method GetInvoices with await since you're returning a Task.

// Set state of progressbar to indeterminate
List<Invoice> result = await GetInvoices();
// Set state of progressbar to nothing
like image 24
Patrick Avatar answered Dec 17 '22 00:12

Patrick