Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
5.2k views
in Technique[技术] by (71.8m points)

c# - Dispose (or Close) killed process

Calling process.Dispose() or process.Close() (no matter which one, 'cos .Close is called inside .Dispose implementation) after process.Kill() sometimes hangs application.

I can't reproduce this bug stable, but sometimes when WaitForExit finishes by timeout passed to it, application hangs on process.Close() command.

Please suggest me, what the cause of this problem may be?

Note:

  • I've seen similar question. But there are not answers & upvoted comment says, that the cause of the problem perhaps at details, which are not provided at that question. So I added more details.
  • I've also seen a linked solution, but I can't use ProcessStartInfo.UseShellExecute = true; 'cos I need to redirect output.

Sorry for verbose code, but I pass it such way, 'cos at similar unanswered question commentators noticed, that not enough details provided (as I noted above)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...