如何取消在C#中启动进程的异步任务? [英] How to cancel a async task that starts a process in 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屋!