当前位置:  开发笔记 > 编程语言 > 正文

如何通过CancellationToken停止异步处理?

如何解决《如何通过CancellationToken停止异步处理?》经验,为你挑选了1个好方法。

我发现在代码下执行某些进程而没有冻结UI.按下"开始工作"按钮时执行此代码.我认为用户可以通过"停止"按钮停止这项工作.所以我在MSDN上发现了这篇文章.. https://msdn.microsoft.com/en-us/library/jj155759.aspx.但是,CancellationToken在这段代码中应用这个很难.任何人都可以帮助解决这个问题吗?

public static async Task RunProcessAsync(string fileName, string args)只使用方法.

代码(来自/sf/ask/17360801/):

public static async Task 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 RunProcessAsync(Process process)
{
    var tcs = new TaskCompletionSource();

    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;
}

用法:

var cancelToken = new CancellationTokenSource();
int returnCode = async RunProcessAsync("python.exe", "foo.py", cancelToken.Token);
if (cancelToken.IsCancellationRequested) { /* something */ }

单击开始按钮时,它会启动一些python脚本.当脚本运行并且用户想要停止它时,用户按下停止按钮.然后程序在代码下执行.

cancelToken.Cancel();

非常感谢你阅读这个问题.



1> svick..:

简单的答案是,您可以在process.Kill()取消令牌时调用:

cancellationToken.Register(() => process.Kill());

但是这有两个问题:

    如果你试图杀死一个尚未存在或已经终止的进程,你会得到一个InvalidOperationException.

    如果你没有Dispose()CancellationTokenRegistration从返回Register(),和CancellationTokenSource长寿命,你有内存泄漏,因为注册将保留在内存中,只要CancellationTokenSource.

根据您的要求和您对清洁代码的需求(即使以复杂性为代价),可以忽略问题#2并通过吞下a中的异常来解决问题#1 catch.

推荐阅读
雯颜哥_135
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有