2012-03-05 4 views
-1

J'essaye de démarrer un processus externe et j'attends qu'il soit actif avant de poursuivre l'exécution de mon programme. Je recherche sur la base du nom du processus, mais j'ai un problème avec ma mise en œuvre si le nom du processus n'est pas ce que je m'attendais.Comment démarrer et attendre un processus externe?

//When Method1 is called, it will load the data and bring a pop up 
//as adobe save dialog box (as a save dialog exe in the task bar) 
Method1(); 

while (true) 
{ 
    foreach (Process clsProcess in Process.GetProcesses()) 
    { 
     if (clsProcess.ProcessName.Contains("AdobeARM")) 
     { 
      isOpened = true; 
     } 
    } 

    //Once the pop up from Method 1 comes i call other methods  
    if (isOpened) 
    { 
     Method2(); 
     Method3(); 
     Method4(); 
     break; 
    } 
} 

Cela pourrait provoquer une boucle infinie si le processus n'est jamais trouvé! Quelle est la meilleure façon de gérer cela ou alternative à while boucle?

+2

'Thread.Sleep (100)' –

+2

fixé une limite de quelque sorte, que ce soit sur le nombre d'essais ou la durée de temps avant que vous renoncez à vérifier. Si vous suivez cette route, vous devriez certainement faire une pause entre les vérifications (comme le suggère @ M.Babcock). – dlev

+0

Est-ce que ceci est prévu pour vérifier et voir s'il fonctionne? ou surveiller et attendre jusqu'à ce qu'il fonctionne? – McAden

Répondre

1

Débarrassez-vous du temps.

Il va effectuer la vérification, puis si le processus AdobeARM est là, il va exécuter vos méthodes et sinon les ignorer. Placez tout ce qu'il y a après Method1 dans une fonction séparée et appelez cette fonction à partir d'un System.Threading.Timer.

Notez que selon la façon dont il est utilisé dans votre application, vous voudrez peut-être ajouter une gestion supplémentaire pour les problèmes de thread.

private Timer myTimer; 

private void DoSomething() 
{ 
    if (myTimer != null) 
    { 
     myTimer.Dispose(); 
     myTimer = null; 
    } 

    Method1(); 

    myTimer = new Timer(CheckForProcess, null, 100, 100); 
} 

private void CheckForProcess(object state) 
{ 
    bool isOpened = false; 
    foreach (Process clsProcess in Process.GetProcesses()) 
    { 
     if (clsProcess.ProcessName.Contains("AdobeARM")) 
     { 
      isOpened = true; 
      break; 
     } 
    } 

    //Once the pop up from Method 1 comes i call other methods  
    if (isOpened) 
    { 
     myTimer.Dispose(); 
     myTimer = null; 
     Method2(); 
     Method3(); 
     Method4(); 
    } 
} 
+0

Même si j'ai essayé, mais je pense qu'en raison d'un problème de timing, cela ne frappe pas le drapeau isOpened et n'appelle pas d'autres méthodes – Sharpeye500

+0

J'ai fait des modifications. re cherche – McAden

+0

'System.Windows.Forms.Timer' ne contient pas un constructeur qui prend 4 arguments, est ce que je reçois, des pensées? – Sharpeye500

0

Peut-être juste faire une pause?

while (true) 
{ 


      foreach (Process clsProcess in Process.GetProcesses()) 
      { 
        if (clsProcess.ProcessName.Contains("AdobeARM")) 
        { 
          isOpened = true; 
        } 
      } 
      //Once the pop up from Method 1 comes i call other methods         
      if (isOpened) 
      { 
      Method2(); 
      Method3(); 
      Method4(); 
      break; 
      } 
      else 
      break; //BREAK HERE, CAUSE NO PROCESSES of ADOBE... 
} 

Si vous voulez venir avec cette fois-ci de code après le temps, utilisez un Timer, mais dans ce cas, évidemment ne pas utiliser plus boucle while.

+0

Je suppose qu'il veut constamment surveiller et réagir lorsque le processus AdobeARM est démarré. Dans ce cas, il ferait tout aussi bien de se débarrasser du «tout» au lieu d'utiliser cette solution. – McAden

+0

Non mettre une pause n'a pas aidé, il a couru la première méthode et a éclaté et n'a pas frappé les autres méthodes. – Sharpeye500

+0

S'il y a un autre meilleur moyen, s'il vous plaît partagez-le.Merci. – Sharpeye500

0

L'utilisation d'un sommeil aide toujours

System.Threading.Thread.Sleep(100); //100ms pause before continuing 

Il a aussi probablement logique d'avoir un compteur ou quelque chose, en supposant que si vous avez mis en boucle pour plus de 500 fois (50 secondes avec ce délai) que vous ne vont pas le trouver et devraient sortir de la boucle. Une pause permettra également de repeindre votre écran, au lieu de bloquer complètement le fil.

+0

Je ne peux pas utiliser Thred.Sleep comme la méthode 1 pourrait retourner moins de données (moins de 100 enregistrements ou plus de données (plus de 5000), donc cela dépend du paramètre, donc je n'ai pas utilisé le sommeil, le sommeil aidera – Sharpeye500

+0

@ Sharpeye500 - Votre question ne contient aucune éventualité concernant le nombre d'enregistrements qui ont été retournés et qui n'a vraiment rien à voir avec votre question ... le problème (tel que vous l'avez décrit) est "_La question ici est si le Le gestionnaire de tâches exe n'a pas quelque chose comme "AdobeARM" et s'il a quelque chose d'autre, ma boucle while ira en boucle infinie._ "Oui, il boucle indéfiniment parce que vous ne lui dites jamais d'arrêter et il va manger beaucoup de Les cycles de l'UC sont à moins que vous ne le disiez –

0

Au lieu d'un certain temps (vrai), essayez une boucle while qui mettra fin en fonction de une valeur de délai d'attente:

//When Method1 is called, it will load the data and bring a pop up 
//as adobe save dialog box (as a save dialog exe in the task bar) 
Method1(); 

//define a "timeout" time one minute from now. (or whatever) 
var timeout = DateTime.Now.AddSeconds(60); 

//loop only while the current time has not exceeded the timeout 
while (DateTime.Now < timeout) 
{ 
    foreach (Process clsProcess in Process.GetProcesses()) 
    { 
     if (clsProcess.ProcessName.Contains("AdobeARM")) 
     { 
      isOpened = true; 
     } 
    } 

    //Once the pop up from Method 1 comes i call other methods  
    if (isOpened) 
    { 
     Method2(); 
     Method3(); 
     Method4(); 
     break; 
    } 
    else 
     Thread.Yield(); //gives other threads CPU time; Thread.Sleep() works too. 
} 

//If we exit the loop without isOpened being set, we should probably tell someone. 
if(!isOpened) throw new Exception("The operation timed out waiting for AdobeARM."); 
+0

+1 pour vous sortir du rouge et puisque c'est comme ça que je le ferais. Question cependant, n'est pas Thread.Yield fondamentalement la même chose que DoEvents? Je suis assez sûr que DoEvents est le fruit de Satan. –

+0

Thread.Yield() est une odeur de code. Je ne l'appellerais pas aussi sévère que Application.DoEvents(). L'utilisation de Yield() ou Sleep() indique une "boucle d'interrogation" (qui est exactement ce que c'est) qui attend que quelque chose d'autre se produise, et il y a généralement une meilleure solution au problème (par exemple un temporisateur). Mon échantillon lui apporte ce dont il a besoin (un moyen de sortir de la boucle infinie que sa construction "while true" créait dans une certaine circonstance) avec une restructuration minimale du code. – KeithS

+0

Un minuteur peut être la solution nettoyante dans son ensemble, mais il semble que ce qu'il a ici est un appel qui invoque un autre processus, puis attend que ce processus se déclenche. Si cela n'arrive jamais, il doit finalement "abandonner", et une minuterie qui sait expirer peut être considérée comme une odeur de code encore plus grande (un gestionnaire d'événements avec des connaissances intimes étroitement couplées sur un objet séparé contenant l'événement auquel il est accroché). à?) – KeithS

1

Vous dites: « Je suis en train de commencer un processus externe et attendez qu'il être actif avant de continuer », donc je suppose que vous utilisez:

Process prc = new Process(...); 
prc.Start(); 

Si oui, je vais appeler

prc.WaitForInputIdle(); 

puis continuer.
A partir de MSDN

WaitForInputIdle - Causes the Process component to wait indefinitely for the associated process to enter an idle state. This overload applies only to processes with a user interface and, therefore, a message loop.

Questions connexes