2010-01-14 47 views
1

對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。

什麼方法最好返回e.Data從原始開關(perl_o)顯示在消息框中?我不知道如何做到這一點。我甚至不確定是否有用於從外部調用perl的最有效的方法。整個應用程序基於perl被外部調用,並返回數據。調用perl的部分已經在第二個線程上運行。任何和所有的幫助,將不勝感激,因爲我是一個初學者...要溫柔:)

編輯: e.Data未聲明。它在調用事件Perl_Output時傳遞。交換機用於基本的網絡命令,在這種情況下:「PERL_TEST」。

未聲明perl_o。我正在尋找一種方法來使perl_o = e.Data AFTER mainproc.process_file完成它的過程。

對我來說最好的總體方法是如果我可以將包含myProcess的函數聲明爲字符串(而不是void),讓函數等待進程完成運行,然後返回進程的輸出。

+0

開關測試是什麼? – 2010-01-14 14:44:13

+0

我認爲你已經消除了太多的代碼。我沒有看到perl_o或e.Data在您的片段中聲明或傳遞......它們來自哪裏?他們如何到達那裏?顯示你的整個方法將有所幫助。 – 2010-01-14 14:45:30

回答

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對象。

+0

哇,夥計,謝謝你的包......我每天都從這塊板子裏學到很多東西。哈哈,如果我知道他們,哇回調會讓我的生活變得更容易。 – cam 2010-01-14 14:59:23

+0

你喜歡這個答案?請注意!最後,你可以接受一個給定的答案(當它解決你的問題時)。 – tanascius 2010-01-14 15:02:01

0

在你的類創建一個StringBuilder成員變量和DataReceivedEventHandler,您連接e.DataStringBuilder成員變量,通過調用其Append()方法。

完成後,您可以在StringBuilder對象上調用ToString(),並獲得所有輸出。

此外,您可能還想爲ErrorDataReceived事件做類似的事情。

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的應用程序將終止,如果緩衝區已滿。閱讀必須在第二個線程上完成。