传递返回的事件数据

时间:2010-01-14 14:34:46

标签: c# perl

对C#来说很新(我会把自己描述为编程的初学者,但我很有野心),所以这可能是非常简单的解决方法。

我在这样的开关中调用了一个函数:

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

mainproc.process是一个调用Perl的函数,如下所示:

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();

Perl_Output函数中不包含任何内容,但接收到args:object o和DataReceivedEventArgs e。

最好从原始开关(perl_o)返回要在消息框中显示的e.Data的方法是什么?我不知道该怎么做。我甚至不确定我是否有最有效的方法从外部调用perl。整个应用程序基于perl被外部调用,并返回数据。调用perl的部分已经在第二个线程上运行。任何和所有的帮助将不胜感激,因为我是一个初学者...温柔:))

编辑: e.Data未声明。它在调用事件Perl_Output时传递。该交换机用于基本网络命令,在这种情况下:“PERL_TEST”。

未声明perl_o。我正在寻找一种方法来使perl_o = e.Data在mainproc.process_file完成它的过程之后。

对我来说最好的总体方法是,如果我可以将包含myProcess的函数声明为字符串(而不是void),让函数等待进程完成运行,然后返回进程的输出。

3 个答案:

答案 0 :(得分:2)

消息是否在switch语句中显示?如果是,那么您可以使用wait handles或类似的方法来阻止当前线程,直到从新进程返回数据,但这可能不是最好的方法。

将回调函数从switch语句传递给函数可能更为明智:

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

然后在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();
}

或类似的东西无论如何,因为我看不到你在哪里使用FileInfo对象。

答案 1 :(得分:1)

您是否知道myProcess.Start()创建了一个并行运行的进程?

您必须从流程中收集输出并等待流程退出。我会这样做:

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;

您还应该从StandardError读取,因为如果perl将某些东西写入那里并且您的应用程序没有读取它,那么如果缓冲区已满,perl应用程序将停止。阅读必须在第二个线程上完成。

答案 2 :(得分:0)

在您的班级和StringBuilder中创建DataReceivedEventHandler成员变量,通过调用e.Data方法将StringBuilder连接到Append()成员变量

完成后,您可以在ToString()对象上拨打StringBuilder并获得所有输出。

此外,您可能希望为ErrorDataReceived事件做类似的事情。