【问题标题】:Cancel task when async called again c#再次调用异步时取消任务c#
【发布时间】:2020-07-21 10:56:10
【问题描述】:

我想创建文件层次结构的树视图,其名称匹配模式并且文件具有搜索词。我需要在任务中运行它并且能够停止和继续此任务或在使用不同参数开始搜索时取消它,我使用 ManualResetEvent 对象完成了停止/继续。但是当再次调用异步函数时,我不知道如何取消此任务(取消令牌不适用于异步函数)。您有什么想法或更好的方法吗?

我演示如何使用 CancellationTokenSource 取消最后一个异步函数调用的代码。

private void buildFileSystemTreeView(TreeNode CurrentTreeNode, DirectoryInfo directoryInfo)
{
    foreach (var f in directoryInfo.GetFiles(this.search_pattern))
    {
        terminate.WaitOne();
        if (this.tokenSource.IsCancellationRequested)
        {
            return;
        }

        CurrentTreeNode.Nodes.Add(f.Name);
        this.CurrentProcessingFileStatusLabel.Text = f.Name;
        this.ProcessedFilesCountStatusLabel.Text = $"{++processed_files_count,3} files processed";
    }

    foreach (var d in directoryInfo.GetDirectories())
    {
        CurrentTreeNode.Nodes.Add(d.Name);
        int i = CurrentTreeNode.Nodes.Count - 1;
        this.buildFileSystemTreeView(CurrentTreeNode.Nodes[i], new DirectoryInfo(d.FullName));
    }
}

async void start_search()
{
    this.tokenSource?.Cancel();
    this.tokenSource = new CancellationTokenSource();
    this.token = tokenSource.Token;
    
    DirectoryInfo directoryInfo = new DirectoryInfo(path);
    this.start_search_treeNode = new TreeNode(directoryInfo.Name);
    await Task.Run(() =>
    {
        Thread.CurrentThread.IsBackground = true;
        this.buildFileSystemTreeView(this.start_search_treeNode, directoryInfo);
    }, token);
}

【问题讨论】:

  • 欢迎来到 StackOverflow!请阅读How to Ask。特别是,请发布您尝试过的代码(不起作用)
  • 你有一个已经是异步的 windows 窗体,所以你不需要添加另一个异步方法。请参阅 msdn 后台工作者示例:docs.microsoft.com/en-us/dotnet/api/…
  • terminate 是什么?你确定代码不会在terminate.WaitOne(); 上阻塞吗?
  • @Selvin terminate 是 ManualResetEvent 对象,你可以用 ManualResetEvent(true) 启动它,这意味着它以信号状态开始

标签: c# winforms


【解决方案1】:

buildFileSystemTreeView 应该将CancellationToken 作为参数。您当前的代码检查tokenSource 字段,并且每次运行search_start 时都会替换该字段。所以它实际上取消的机会很小。

在处理这样的多线程代码时,如果您从不更改由多个线程访问的任何内容,这将很有帮助。除了显式线程安全的东西,比如cancellationToken。例如

this.CurrentProcessingFileStatusLabel.Text = f.Name;

可能会失败,因为 UI 类型只能由主线程安全访问。 CurrentTreeNode.Nodes.Add(f.Name) 可能也不安全。

【讨论】:

    猜你喜欢
    • 2018-07-20
    • 1970-01-01
    • 2016-05-08
    • 1970-01-01
    • 2017-10-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多