问题
I found beneath code for execute some process without freezing UI. This code is executed when 'Start Work' button is pressed. And I think users would stop this work by 'Stop' button. So I found this article at MSDN.. https://msdn.microsoft.com/en-us/library/jj155759.aspx . But, It was hard that applying this CancellationToken
at this code.. Anyone can help this problem?
I use public static async Task<int> RunProcessAsync(string fileName, string args)
method only.
Code (From https://stackoverflow.com/a/31492250):
public static async Task<int> RunProcessAsync(string fileName, string args)
{
using (var process = new Process
{
StartInfo =
{
FileName = fileName, Arguments = args,
UseShellExecute = false, CreateNoWindow = true,
RedirectStandardOutput = true, RedirectStandardError = true
},
EnableRaisingEvents = true
})
{
return await RunProcessAsync(process).ConfigureAwait(false);
}
}
// This method is used only for internal function call.
private static Task<int> RunProcessAsync(Process process)
{
var tcs = new TaskCompletionSource<int>();
process.Exited += (s, ea) => tcs.SetResult(process.ExitCode);
process.OutputDataReceived += (s, ea) => Console.WriteLine(ea.Data);
process.ErrorDataReceived += (s, ea) => Console.WriteLine("ERR: " + ea.Data);
bool started = process.Start();
if (!started)
{
//you may allow for the process to be re-used (started = false)
//but I'm not sure about the guarantees of the Exited event in such a case
throw new InvalidOperationException("Could not start process: " + process);
}
process.BeginOutputReadLine();
process.BeginErrorReadLine();
return tcs.Task;
}
Usage :
var cancelToken = new CancellationTokenSource();
int returnCode = async RunProcessAsync("python.exe", "foo.py", cancelToken.Token);
if (cancelToken.IsCancellationRequested) { /* something */ }
When the start button clicked, it starts some python script. When script is running and user wants to stop it, user presses stop button. Then program executes below code.
cancelToken.Cancel();
Thank you very much for reading this question.
回答1:
The simple answer is that you can just call process.Kill()
when the token is canceled:
cancellationToken.Register(() => process.Kill());
But there are two problems with this:
- If you attempt to kill a process that doesn't exist yet or that has already terminated, you get an
InvalidOperationException
. - If you don't
Dispose()
theCancellationTokenRegistration
returned fromRegister()
, and theCancellationTokenSource
is long-lived, you have a memory leak, since the registrations will stay in memory as long as theCancellationTokenSource
.
Depending on your requirements, and your desire for clean code (even at the cost of complexity) it may be okay to ignore problem #2 and work around problem #1 by swallowing the exception in a catch
.
来源:https://stackoverflow.com/questions/34199628/how-can-i-stop-async-process-by-cancellationtoken