简体   繁体   中英

Why don't my event handlers fire when I'm reading from the standard output of another process

I have a very simple C# project that has a UI process and a worker process. The worker code needs to be a process (rather than a thread) because it can be run by either the UI or by the Windows Task Scheduler.

In the UI code, I set the ProcessStartInfo.RedirectStandardOutput to true and I register the event handlers. Then, I start the process (with Process.Start() and call Process.BeginOutputReadline() . Yet, the method that I have designated as the OutputDataReceived event handler never fires. When I run the worker process without redirecting it's standard output, I see the expected output on the console. When I turn on output redirection, I don't see anything on the console (as expected), but the event handlers don't fire either. Is there something else that I need to to read asynchronously from another process' standard output stream?

EDIT: I've managed to replicate the problem with two simple console processes.

First the parent:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace OutputRedirectionEventHandlerTest
{
    class ParentProgram
    {
        static void Main(string[] args)
        {
            ProcessStartInfo processInfo = new ProcessStartInfo()
            {
                FileName = "OutputRedirectionWorker.exe",
                RedirectStandardOutput = true,
                UseShellExecute = false
            };
            Process subProcess = new Process()
            {
                StartInfo = processInfo
            };
            subProcess.OutputDataReceived += 
                new DataReceivedEventHandler(OutputHandler);
            subProcess.Start();
            subProcess.BeginOutputReadLine();


        }

        static void OutputHandler(object SendingProcess, 
            DataReceivedEventArgs args)
        {
            Console.Out.WriteLine("Received from subprocess: " + args.Data);
        }

    }
}

And then, the child:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;

namespace OutputRedirectionWorker
{
    class ChildProgram
    {
        static void Main(string[] args)
        {
            Console.Out.WriteLine("Output1");
            Console.Out.WriteLine("Output2");
            Console.Out.WriteLine("Output3");
            Thread.Sleep(10000);
        }

    }
}

No output ever gets printed by the parent.

You need to understand that the call to BeginOutputReadLine returns immediately . It kicks off an asynchronous read of standard output.

The problem in the example that you provided is that the Parent program exits immediately after calling BeginOutputReadLine . It never has a chance to read the output- it is exiting before the ChildProgram even starts. You need to keep the parent running using a loop of some kind in order for it to read the standard output.

Try something like this:

static void Main(string[] args)
    {
        ProcessStartInfo processInfo = new ProcessStartInfo()
        {
            FileName = "OutputRedirectionWorker.exe",
            RedirectStandardOutput = true,
            UseShellExecute = false
        };
        Process subProcess = new Process()
        {
            StartInfo = processInfo
        };
        subProcess.OutputDataReceived += 
            new DataReceivedEventHandler(OutputHandler);
        subProcess.Start();
        subProcess.BeginOutputReadLine();

        while (Console.ReadLine().ToLower() != "quit") {
            // looping here waiting for the user to type quit
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM