получить длительный прогресс процесса в функции асинхронной задачи - PullRequest
0 голосов
/ 11 февраля 2019

У меня есть асинхронная функция, и я использовал Progress

для выполнения длительного процесса. После запуска другой задачи кажется, что запущено много отчетов о ходе выполнения.

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

}

и это мой 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;
    }
}

, и в результате вы можете видеть разные значения в прогрессбар одновременно.enter image description here

1 Ответ

0 голосов
/ 11 февраля 2019

Короче говоря, вы не используете CancellationTokenSource правильно по 2 причинам;во-первых, его нужно передать любым async методам, которые вы вызываете, чтобы действительно отменить их, во-вторых, скорее всего, ему придется жить дольше, чем просто внутри области, в которой вы его используете.

Попробуйте что-то вроде этого (дополните комментариями, чтобы, надеюсь, было легче следить):

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.
}
...