如何取消在C#中启动进程的异步任务? [英] How to cancel a async task that starts a process in C#?

查看:312
本文介绍了如何取消在C#中启动进程的异步任务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前,我的代码从svn运行签出,并使用以下两个任务将stdout和stderr重定向到文本框.我希望能够在用户单击StopButton时立即取消任务,并能够取消下载.我了解,如果我将cmd.exe命令更改为诸如"Pause"之类的内容(一直运行到用户单击某些内容),则可以使用StopButton取消此命令.我是C#的新手,试图理解为什么我可以取消该命令而不是svn下载.

Currently my code runs a checkout from svn and redirections the stdout and stderr to a textbox using two tasks as seen below. I want to be able to cancel the task immediately when a user clicks the StopButton and be able to cancel the download. I understand that if I changed my cmd.exe command to say something such as "Pause", which continues to run until a user clicks something, I can cancel this command with the StopButton. I am very new to C# and trying to understand why I can cancel that command and not the svn download.

这是我应该实现代码的一种方式还是应该尝试其他方法?

Is this a way I should be implementing my code or should I try a different method?

非常感谢您的帮助!我真的很感激!

Thanks so much for the help! I truly appreciate it!

   public Form2()
    {
        InitializeComponent();

    }

    private TaskCompletionSource<bool> _cancelTask;

    private async Task RunProcess()
    {
        Process process = new Process
        {
            StartInfo = new ProcessStartInfo
            {
                FileName = "cmd.exe",
                Arguments = "svn download"
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                CreateNoWindow = false,
            }
        };


        Console.Write(URL);
        process.Start();

        Task readerTasks = Task.WhenAll(
            ConsumeReader(process.StandardError),
            ConsumeReader(process.StandardOutput));

        Task completedTask = await Task.WhenAny(readerTasks, _cancelTask.Task);

        if(completedTask == _cancelTask.Task)
        {
            process.Kill();
            await readerTasks;
            throw new TaskCanceledException(_cancelTask.Task);
        }
    }

    private async Task ConsumeReader(TextReader reader)
    {
        char[] text = new char[512];
        int cch;

        while ((cch = await reader.ReadAsync(text, 0, text.Length)) > 0)
        {
            textBox2.AppendText(new string(text, 0, cch));
        }
    }

    private async void Submit_Click(object sender, EventArgs e)
    {

        Submit.Enabled = false;
        StopButton.Enabled = true;
        _cancelTask = new TaskCompletionSource<bool>();

        try
        {
            await RunProcess(cts.Token);
        }
        catch (OperationCanceledException)
        {
            MessageBox.Show("The operation was cancelled");
        }
        finally
        {
            _cancelTask = null;
            Submit.Enabled = true;
            StopButton.Enabled = false;
        }
    }

    private void StopButton_Click(object sender, EventArgs e)
    {
        _cancelTask.SetCanceled();
    }

推荐答案

我找到了一个解决方案,不确定是否最好,但是您可以启动另一个进程来启动命令行命令taskkill,以杀死所有.exe文件.正在运行.我现在杀死了从cmd.exe调用的cmd.exe(父)和svn.exe(子)!

I found a solution, not sure if this is the best, but you can start another process to start the command line command taskkill to kill all of the .exe's that are running. I now kill the cmd.exe (parent) and the svn.exe (child) that was called from the cmd.exe!

仅当您知道从父级启动的.exe(如果创建了更多子级)时才有用,最好找到其他解决方案来递归地查找子级进程.

This is only useful if you know the .exes that are started from the parent if there were many more children created it would be best to find a different solution to recursively go and find the children processes.

    if(completedTask == _cancelTask.Task)
    {
        //process.Kill(); This would only kill the CMD.exe
        Process exit = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName = "cmd.exe",
                    //Arguments = "/K Pause",
                    Arguments = "/C taskkill /f /im svn.exe & taskkill /f /im cmd.exe",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = false,
                }
            };
            exit.Start();
        await readerTasks;
        throw new TaskCanceledException(_cancelTask.Task);
    }

这篇关于如何取消在C#中启动进程的异步任务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆