开发者

Passing returned event data

Pretty new to C# (and I would describe myself as a beginner in programming, but I'm ambitious), so this is probably something very simple to solve.

I have a function getting called in a switch like this:

            case "PERL_TEST":
            FileInfo fi = new FileInfo("hello.txt");
            mainproc.process_file(fi);
            MessageBox.Show(perl_o);                
            break;

The mainproc.process is a function that calls Perl like this:

myProcess = new Process();
        ProcessStartInfo myProcessStartInfo = new ProcessStartInfo("perl.exe");
        myProcessStartInfo.Arguments = "perly.pl";
        myProcessStartInfo.UseShellExecute = false;
        myProcessStartInfo.RedirectStandardOutput = true;
        myProcessStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        myProcessStartInfo.CreateNoWindow = true;
        myProcess.StartInfo = myProcessStartInfo;
        myProcess.OutputDataReceived += new DataReceivedEventHandler(Perl_Output);
        myProcess.Start();
        myProcess.BeginOutputReadLine();

The P开发者_运维知识库erl_Output function contains nothing in it, but receives the args: object o, and DataReceivedEventArgs e.

What method would be best to return e.Data to be shown in the messagebox from the original switch (perl_o)? I'm not sure how to do this. I'm not even sure if I have the most efficient method for calling perl externally. The whole application is based on perl being called externally, and returning the data. The part that calls perl is already running on a second thread. Any and all help would be appreciated as I am a beginner... be gentle :)

Edit: e.Data is not declared. It is passed when the event Perl_Output is called. The switch is for basic network commands, in this case: "PERL_TEST".

perl_o is not declared. I'm looking for a way to make perl_o = e.Data AFTER mainproc.process_file finishes it's process.

The best overall way for me would be if I could declare the function containing myProcess as string (instead of void), have the function wait for the process to finish running, then return the output of the process.


Does the message have to be shown in the switch statement? If it does, then you could use wait handles or similar to block the current thread until data are returned from the new process, but this is likely not the best approach.

It might be more sensible to pass a callback into the function from the switch statement:

case "PERL_TEST":
    FileInfo fi = new FileInfo("hello.txt");
    mainproc.process_file(fi, MessageBox.Show);
    break;

Then in process_file:

public void process_file(FileInfo fi, Action<string> dataCallback)
{
    myProcess = new Process();
    ProcessStartInfo myProcessStartInfo = new ProcessStartInfo("perl.exe");
    myProcessStartInfo.Arguments = "perly.pl";
    myProcessStartInfo.UseShellExecute = false;
    myProcessStartInfo.RedirectStandardOutput = true;
    myProcessStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    myProcessStartInfo.CreateNoWindow = true;
    myProcess.StartInfo = myProcessStartInfo;
    myProcess.OutputDataReceived += (sender, e) =>
        {
            dataCallback(e.Data);
        };
    myProcess.Start();
    myProcess.BeginOutputReadLine();
}

Or something similar to this anyway, as I can't see where you're using the FileInfo object.


Did you know that myProcess.Start() creates a process that runs in parallel?

You have to collect the output from the process and wait for the process to exit. I would do it like this:

myProcess.Start();
string perl_o, error;
Thread readStandardOutput = new Thread((ThreadStart)delegate 
{ 
    perl_o = myProcess.StandardOutput.ReadToEnd(); 
});  
Thread readStandardError = new Thread((ThreadStart)delegate 
{ 
    error = myProcess.StandardOutput.ReadToEnd(); 
});  

myProcess.WaitForExit();    // wait until the process exits
readStandardOutput.Join();  // wait until the thread has read all data
readStandardError.Join();   // wait until the thread has read all data
int exitCode = p.ExitCode;  // if you need the exit code from perl
return perl_o;

You should also read from StandardError because if perl write somethings to there and your app don't read it, the perl app will halt if the buffer is full. Reading has to be done on a second thread.


Create a StringBuilder member variable in your class and in the DataReceivedEventHandler, you concatenate e.Data to your StringBuilder member variable, by calling its Append() method.

Once you're done, you call ToString() on your StringBuilder object and you have all the output.

Also, you may want to do a similar thing for the ErrorDataReceived event.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜