-1

I have a async function and used the Progress< int>

to progress long process After I run another task, it seems that the many progress reports are running.

private async void Listbox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var progress = new Progress<int>(percent =>
                    {
                        prg.Value = percent;
                    });
    isCanceled = true;
    await ExecuteManuallyCancellableTaskAsync(progress);

}

and this is my func

public async Task ExecuteManuallyCancellableTaskAsync(IProgress<int> progress)
{
    var mprogress = 0;
    prg.Value = 0;
    using (var cancellationTokenSource = new CancellationTokenSource())
    {
        cancellationTokenSource.Cancel();

        var SearchTask = Task.Run(async () =>
        {
            foreach (var file in await GetFileListAsync(GlobalData.Config.DataPath))
            {
                if (isCanceled)
                {
                    cancellationTokenSource.Cancel();
                    return;
                }
                mprogress += 1;
                progress.Report((mprogress * 100 / TotalItem));

                await Dispatcher.InvokeAsync(() =>
                {
                    // my codes
                }, DispatcherPriority.Background);
            }
        });

        await SearchTask;
    }
}

and this is result that you can see different value in progressbar same time. enter image description here

Bijington
  • 3,661
  • 5
  • 35
  • 52
  • and where are you using `cancellationTokenSource.Token` ? ... also where are you setting `isCanceled` to false? – Selvin Feb 10 '19 at 21:44
  • @Selvin isCanceled is bool when i run my func i set it to true and in func i check if true i call cancellationTokenSource.Cancel(); i dont have token –  Feb 10 '19 at 21:50
  • I assume somewhere in your code you are also setting `isCanceled = false;'. Is this correct? – Bijington Feb 10 '19 at 21:50
  • You never use `cancellationTokenSource` so doing `cancellationTokenSource.Cancel()` does literally nothing ... even if, `isCanceled` is not set to `true` when it hits `if` in other case it would at least leave the `foreach` loop – Selvin Feb 10 '19 at 21:52
  • @Selvin how can i fix this? –  Feb 10 '19 at 21:57
  • @Bijington yes... –  Feb 10 '19 at 21:58
  • By understanding how to cancel tasks, by understanding how accessing to the same variable works from different tasks - maybe some C# course – Selvin Feb 10 '19 at 21:59

1 Answers1

1

In short you are not using the CancellationTokenSource correctly for 2 reasons; firstly it needs to be passed around to any async methods that you are calling in order to truly cancel them, secondly it will likely need to live for longer than just inside the scope where you are using it.

Try something like this (complete with comments to hopefully make it easy to follow):

private CancellationTokenSource cancellationTokenSource; // And remove isCanceled as this is causing some of the issues
private async void Listbox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var progress = new Progress<int>(percent =>
                    {
                        prg.Value = percent;
                    });

    // Make sure any current processing is stopped.
    cancellationTokenSource?.Cancel();

    // Prepare to be able to cancel the next round of processing.
    cancellationTokenSource = new CancellationTokenSource();

    await ExecuteManuallyCancellableTaskAsync(progress, cancellationTokenSource.Token);
}
public async Task ExecuteManuallyCancellableTaskAsync(IProgress<int> progress, CancellationToken cancelToken)
{
    var mprogress = 0;
    prg.Value = 0;

    await Task.Run(async () =>
    {
        // You will need to implement checks against the CancellationToken in your GetFileListAsync method also.
        foreach (var file in await GetFileListAsync(GlobalData.Config.DataPath, cancelToken))
        {
            mprogress += 1;
            progress.Report((mprogress * 100 / TotalItem));

            // Only update the UI if we have not been requested to cancel.
            if (!cancelToken.IsCancellationRequested)
            {
                await Dispatcher.InvokeAsync(() =>
                {
                    // my codes
                }, DispatcherPriority.Background);
            }
        }
    }, cancelToken); // Pass in the token to allow the Task to be cancelled.
}
Bijington
  • 3,661
  • 5
  • 35
  • 52