简体   繁体   English

在异步任务功能中获得较长的过程进度

[英]get long process progress in async task function

I have a async function and used the Progress< int> 我有一个异步函数,并使用了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. 结果是您可以同时在进度栏中看到不同的值。 在此处输入图片说明

In short you are not using the CancellationTokenSource correctly for 2 reasons; 简而言之,由于两个原因,您没有正确使用CancellationTokenSource 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. 首先,它需要传递给您正在调用的任何async方法以真正取消它们;其次,它可能需要生存的时间比仅在使用它的作用域内更长。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM