【问题标题】:get long process progress in async task function在异步任务功能中获得较长的进程进度
【发布时间】:2019-02-10 21:28:57
【问题描述】:

我有一个异步函数并使用了 Progress

进行长进程在我运行另一个任务后,似乎许多进度报告正在运行。

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

}

这是我的功能

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

这是您可以同时在进度条中看到不同值的结果。

【问题讨论】:

  • 你在哪里使用cancellationTokenSource.Token? ...还有你在哪里将isCanceled 设置为假?
  • @Selvin isCanceled 是布尔值,当我运行我的 func 时,我将其设置为 true,在 func 中我检查是否为 true,我调用了 cancelTokenSource.Cancel();我没有令牌
  • 我假设在您的代码中某处您也设置了“isCanceled = false;”。这是正确的吗?
  • 你永远不会使用cancellationTokenSource,所以这样做cancellationTokenSource.Cancel()实际上什么都不做......即使isCanceled在遇到true时没有设置为true,在其他情况下它会在至少离开foreach 循环
  • @Selvin 我该如何解决这个问题?

标签: c# wpf asynchronous async-await progress


【解决方案1】:

简而言之,您没有正确使用CancellationTokenSource 有两个原因;首先,它需要传递给您正在调用的任何 async 方法才能真正取消它们,其次,它可能需要比仅在您使用它的范围内生存更长的时间。

尝试这样的事情(用 cmets 完成,希望它更容易理解):

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

【讨论】:

    猜你喜欢
    • 2020-05-25
    • 2013-09-25
    • 1970-01-01
    • 2018-12-26
    • 1970-01-01
    • 1970-01-01
    • 2017-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多