我有一个异步函数和所使用的进展<int>的
我再跑任务后进步漫长的过程,似乎许多进度报告正在运行。
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;
}
}
总之你没有正确使用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.
}