取消所有正在运行的任务

时间:2019-02-16 18:17:30

标签: c# wpf asynchronous async-await task

我无法停止创建的任务以下代码将不会发生

ts?.Cancel();

这就是我运行任务的方式

ts = new CancellationTokenSource();
await ((ViewModel)DataContext).loadTitles(progressTitle, ts.Token, prg);

和在视图模型中

public async Task loadTitles(IProgress<int> progress, CancellationToken ct, ProgressBar prg)
        {
             if (!ct.IsCancellationRequested)
        {
            foreach (var line in System.IO.Directory.EnumerateFiles(GlobalData.Config.DataPath, "*.jpg", SearchOption.AllDirectories))
            {
                mprogress += 1;
                progress.Report((mprogress * 100 / totalFiles));
                var item = ShellFile.FromFilePath(line);

                ArtistNames.Add(new ArtistData
                {
                    Name = item.Properties.System.Title.Value,
                    Tag = line
                });
                await Task.Delay(5);
            }
        }

        }

对于其他四个功能,我编写了与同一功能相似的代码,并且任务已很好地停止,但是该功能无法正常工作。

2 个答案:

答案 0 :(得分:1)

您无法停止您的任务,因为在loadTitle方法的开始处,您检查是否请求取消。但这不是,也可能不是,因为您立即进入了foreach循环。您需要在循环中检查它:

public async Task loadTitles(IProgress<int> progress, CancellationToken ct, ProgressBar prg)
{
    foreach (var line in System.IO.Directory.EnumerateFiles(GlobalData.Config.DataPath, "*.jpg", SearchOption.AllDirectories))
    {
        if (ct.IsCancellationRequested)
        {
            break;
        }

        // ... the rest of your code
    }
}

答案 1 :(得分:1)

除了第一行之外,没有其他方法可以监听CancellationToken

如果要实现正常取消,请在循环内测试令牌并将其传递给Task.Delay

请注意,如果loadTitles是从UI线程中调用的,则它大多在同一UI线程中运行,因为这里除了Task.Delay之外没有任何异步方法,它保留了调用者上下文并在UI中继续执行异步方法线。为避免这种情况,您需要在ConfigureAwait(false)之后调用Task.Delay