Skip to content

Użycie IProgress i CancellationToken

Pisząc aplikację wielowątkowe często istnieje potrzeba raportowania aktualnego postępu lub przerwania obliczeń „z zewnątrz”.
Klasa BackgroundWorker dostarcza do tego gotowe metody. Jednak jak to zrobić gdy pracujemy z klasą Task?

 

1) Raportowanie:

 

Jednym z możliwych sposobów, rozwiązania tego problemu, jest użycie obiektów implementujących interface IProgress<T>.
Metoda, która ma wykonywać się asynchronicznie, jako parametr powinna przyjmować obiekty typu IProgress<T>:

Task DoSomeWorkAsync(IProgress<int> progress)

Obiekt ten zawiera metodę Report(T), która jako parametr przyjmuje typ generyczny w tym przypadku będzie to int.
Wywołanie tych obliczeń wygląda w następujący sposób:

var progressIndicator = new Progress<int>(ReportProgress);
await DoSomeWorkAsync(progressIndicator, token);
.
.
.
private Task DoSomeWorkAsync(IProgress<int> progress)
{
    return Task.Run(() =>
    {
        for (int i = 0; i < int.MaxValue; i++)
        {
            progress.Report(i);
        }
    });
}

do tego metoda raportująca:

private void ReportProgress(int value)
{
    Console.WriteLine("Current progress: {0}", value);
}

2) Przerwanie obliczeń:

 

Do metody asynchronicznej przekazujemy dodatkowy parametr: CancellationToken.
Dzięki temu możemy, wewnątrz metody, sprawdzać czy nie przyszło żądanie o przerwanie obliczeń.
Wystarczy sprawdzić stan flagi IsCancellationRequested.

        private Task DoSomeWorkAsync(CancellationToken cancellationToken)
        {
            return Task.Run(() =>
            {
                for (int i = 0; i < int.MaxValue; i++)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }
                }
            });
        }

wywołanie metody w tym przypadku wygląda tak:

var cts = new CancellationTokenSource();
var token = cts.Token;
await DoSomeWorkAsync(token);

oraz żądanie przerwania:

cts.Cancel();

Cały działający kod z przykładem (pomimo tego, że ma on tylko 55 linii) jak zawsze dostępny na GitHub 😉

Published inProgramowanie

Be First to Comment

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *