1

目前,我的代码从 svn 运行结帐,并使用如下所示的两个任务将 stdout 和 stderr 重定向到文本框。当用户单击 StopButton 并能够取消下载时,我希望能够立即取消任务。我了解,如果我将 cmd.exe 命令更改为说出诸如“暂停”之类的内容,它会继续运行直到用户单击某些内容,我可以使用 StopButton 取消此命令。我对 C# 非常陌生,并试图理解为什么我可以取消该命令而不是 svn 下载。

这是我应该实现代码的方式还是应该尝试不同的方法?

非常感谢你的帮忙!我真的很感激!

   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();
    }
4

1 回答 1

0

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

这仅在您知道从父级启动的 .exe 文件时才有用,如果创建了更多子级,最好找到一个不同的解决方案来递归地查找子进程。

    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);
    }
于 2016-08-11T21:37:45.203 回答