quanticle
quanticle

Reputation: 5020

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.

Upvotes: 0

Views: 294

Answers (1)

Chris Shain
Chris Shain

Reputation: 51369

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

Upvotes: 1

Related Questions