2010-01-14 5 views
1

Assez nouveau en C# (et je me décrirais comme un débutant en programmation, mais je suis ambitieux), donc c'est probablement quelque chose de très simple à résoudre.Passer les données d'événement retournées

J'ai une fonction appelée se dans un commutateur comme celui-ci:

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

Le mainproc.process est une fonction qui appelle Perl comme ceci:

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

La fonction Perl_Output contient rien dans ce , mais reçoit les arguments: object o et DataReceivedEventArgs e.

Quelle méthode serait la meilleure pour renvoyer e.Data à afficher dans la boîte à messages à partir du commutateur d'origine (perl_o)? Je ne suis pas sûr de savoir comment faire ça. Je ne suis même pas sûr si j'ai la méthode la plus efficace pour appeler Perl en externe. L'application entière est basée sur l'appel externe de perl, et le retour des données. La partie qui appelle perl est déjà en cours d'exécution sur un deuxième thread. Toute aide serait appréciée car je suis un débutant ... soyez gentil :)

Editer: e.Data n'est pas déclaré. Il est passé lorsque l'événement Perl_Output est appelé. Le commutateur est pour les commandes réseau de base, dans ce cas: "PERL_TEST".

perl_o n'est pas déclaré. Je cherche un moyen de faire perl_o = e.Data APRES mainproc.process_file termine son processus. La meilleure façon générale pour moi serait si je pouvais déclarer la fonction contenant myProcess comme une chaîne (au lieu de void), avoir la fonction d'attendre que le processus se termine, puis retourner la sortie du processus.

+0

Que vérifie le commutateur? –

+0

Je pense que vous avez enlevé un peu trop de votre code. Je ne vois pas perl_o ou e.Data déclaré ou passé dans vos extraits ... d'où viennent-ils? Comment arrivent-ils là? Montrer toutes vos méthodes vous aidera. –

Répondre

2

Le message a-t-il pour être affiché dans l'instruction switch? Si c'est le cas, vous pouvez utiliser wait handles ou similaire pour bloquer le thread en cours jusqu'à ce que les données soient renvoyées par le nouveau processus, mais ce n'est probablement pas la meilleure approche.

Il pourrait être plus judicieux de passer un rappel dans la fonction de l'instruction switch:

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

Puis, en 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(); 
} 

Ou quelque chose de semblable à cela de toute façon, que je peux » t voyez où vous utilisez l'objet FileInfo.

+0

Wow, mec, merci un paquet ... J'apprends tellement tous les jours de ce forum. Haha, wow callbacks aurait rendu ma vie tellement plus facile si j'avais su à leur sujet. – cam

+0

Vous aimez cette réponse? S'il vous plaît upvote! Et enfin, vous pouvez accepter l'une des réponses données (quand cela résout votre problème). – tanascius

0

Créer une variable membre StringBuilder dans votre classe et dans le DataReceivedEventHandler, vous concaténer e.Data à votre variable membre StringBuilder, en appelant sa méthode Append().

Une fois que vous avez terminé, vous appelez ToString() sur votre objet StringBuilder et vous avez tous les résultats.

En outre, vous souhaiterez peut-être effectuer une opération similaire pour l'événement ErrorDataReceived.

1

Saviez-vous que myProcess.Start() crée un processus qui s'exécute en parallèle?

Vous devez collecter la sortie du processus et attendre la fin du processus.Je le ferais comme ceci:

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; 

Vous devriez également lire à partir StandardError parce que si perl écrivent somethings y et votre application ne lisent pas, l'application Perl arrêtera si le tampon est plein. La lecture doit être faite sur un deuxième fil.

Questions connexes