处置或关闭被杀死的进程

问题描述

process.dispose() 之后调用 process.Close().Close(无论是哪一个,'cos .disposeprocess.Kill() 实现中被调用)有时会挂起应用程序。>

我无法稳定地重现此错误,但有时当 WaitForExit 通过传递给它的超时完成时,应用程序挂起 process.Close() 命令。

请给我建议,这个问题的原因可能是什么?

注意:

抱歉,代码冗长,但我是这样传递的,因为在类似的未回答问题评论员注意到,没有提供足够的细节(正如我上面提到的)

private static async Task<int> RunMethod(string processArguments)
{
    // 1. Prepare processstartinfo

    processstartinfo startInfo = new processstartinfo();

    startInfo.Arguments = processArguments;
    startInfo.RedirectStandardOutput = true;
    startInfo.RedirectStandardError = true;
    startInfo.CreateNowindow = true;
    startInfo.UseShellExecute = false;

    // 2. Create process inside using-block to be disposed

    using (var proc = new Process())
    {
        proc.StartInfo = startInfo;

        // 3. Subscribe output streams handlers

        proc.OutputDataReceived += (sender,outputLine) => { HandleMessage(outputLine); };
        proc.ErrorDataReceived  += (sender,errorLine)  => { HandleMessage(errorLine); };

        // 4. Start process

        if (!proc.Start())
        {
            proc.Close();
            return -1;
        }

        // 5. Start the asynchronous read of the standard output stream.

        proc.BeginoutputReadLine();
        proc.BeginErrorReadLine();

        // 6. Waiting process to exit with timeout on threadpool to not block UI thread

        // Re#er warns me "captured variable `proc` is disposed in the outer scope". But I think it's Ok,'cos we're awaiting this task inside using block (in next line)
        var waitingProcesstask = Task.Run(() => proc.WaitForExit(TIMEOUT),_cancelToken);
        bool hasExited = await waitingProcesstask;

        // 7. Stop reading streams

        // Not sure,these 2 CalncelXxxRead methods are needed. But hope it won't hurt at least
        proc.CancelErrorRead();
        proc.CancelOutputRead();

        // 8. If !hasExited (i.e. TIMEOUT is reached) we kill the process

        if (!hasExited)
        {
            Logger.Debug("0. Before Kill()");

            proc.Kill();
            proc.Refresh(); // not sure,it's needed
        }

        // If uncomment next 2 lines,then problem moves here from end of using block
        //proc.Close();
        //Logger.Debug("1. after .Close call");  // <------------------ This log we don't see sometimes
        
        Logger.Debug("2. last inside using-block");
    } // end of using block

    Logger.Debug("3. after using-block");  // <------------------ This log we don't see sometimes (if `.Close` wasn't called before)
    
    return 0;
}

解决方法

我已经解决了我的问题。问题是:我的进程偶尔**会产生子守护进程,它可以永远工作。如果父流被重定向,子进程(按设计)总是继承重定向的输出流。

另一方面,.Kill() 不会杀死子进程 - 仅针对它被调用。 (直到 .Net 5.0,其中 .Kill(bool) 解决了这个问题)。

所以 .Dispose().Close() 永远不会完成,'cos 等待释放由无限子进程持有的输出流。

弄清楚发生了什么是非常有趣的冒险 =)


**) - 这就是复制非常不稳定的原因

PS:感谢@Blindy 为我指明了非常接近问题真正原因所在的方向。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...