我有一个异步功能,并使用了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;
}
}
答案 0 :(得分:2)
简而言之,由于两个原因,您没有正确使用CancellationTokenSource
;首先,它需要传递给您正在调用的任何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.
}