Friday 24 February 2017

Waitforexit Asynchrone

Le code ressemble presque à ceci: Comme vous pouvez le voir, le code lance un processus cmd. exe et lui passe la commande que je souhaite exécuter. Je redirige StandardError et StandarOutput afin de les lire à partir du code. Le code les lit avant le processus. WaitForExit (Timeout) appel comme recommandé par Microsoft (plus sur cela plus tard). Le problème se produit si la commande que j'envoie à cmd. exe ne se termine jamais ou ne se bloque indéfiniment. Dans le code j'ai utilisé la commande ping - t 8.8.8.8 qui, à cause de l'option - t, pings l'hôte sans s'arrêter. Ce qui se passe Le processus cmd. exe avec la commande ping - t ne quitte jamais et ne ferme jamais le flux stdout et donc notre code se bloque à la ligne Output. StandardOutput. ReadToEnd () car il ne peut pas réussir à lire tout le flux. La même chose se produit également si une commande dans un fichier de commandes se bloque pour une raison quelconque et que le code ci-dessus peut fonctionner continuellement pendant des années et puis se bloquer soudainement sans raison apparente. Avant que j'écrive que son recommandé de lire les flux redirigés avant le processus. WaitForExit (Timeout) appel, bien cela est particulièrement vrai si vous utilisez la signature WaitForExit sans le délai d'attente. Si vous appelez processus. WaitForExit () avant de lire les flux redirigés: code 2: vous pouvez rencontrer un blocage si la commande que vous attachez à cmd. exe ou le processus que vous appelez remplit la sortie standard ou l'erreur standard. Ceci parce que notre code ne peut atteindre le processus de sortie lignes. StandardOutput. ReadToEnd () En fait, le processus enfant (la commande ping ou un fichier batch ou tout autre processus que vous exécutez) ne peut pas continuer si notre programme ne lit pas les tampons remplis des flux et cela ne peut pas arriver car le code est suspendu à La ligne avec le processus. WaitForExit () qui attendra pour toujours le projet enfant à quitter. La taille par défaut des deux flux est 4096 octets. Vous pouvez tester ces deux tailles avec ces fichiers batch: Le premier script écrit 4096 octets à la sortie standard et le second à l'erreur standard. Enregistrez l'un de ces dans C: testbuffsize. bat et exécutez notre processus d'appel de programme. WaitForExit () avant le processus de sortie. StandardOutput. ReadToEnd () comme dans le code 2. Vous pouvez le faire en écrivant CommandResult Résultat ExecuteShellCommandSync (c: testbuffsize. bat, 1000) à la ligne 13 du code 1. Le code ne sera pas suspendre, mais si vous écrivez un octet de plus dans l'un des deux flux, il débordera la taille du tampon de faire le programme pendre. Si vous avez besoin de rediriger et de lire la sortie standard ou l'erreur standar, la meilleure solution est de les lire de manière asynchrone. Un excellent moyen de le faire est proposé par Mark Byers dans ce thread stackoverflow Comme la dernière chose s'il vous plaît noter que si le processus enfant se ferme uniquement parce que vous utilisez le processus. WaitForExit (Timeout) signature et il va effectivement en timeout vous devez tuer le processus cmd. exe et ses enfants possibles. Comment utiliser Process. Start dans Visual Basic. NET Par Dan Mabbutt. Visual Basic Expert La méthode Start de l'objet Process est peut-être l'un des outils les plus sous-estimés à votre disposition en tant que programmeur. Comme une méthode. NET, Start a une série de surcharges (différents ensembles de paramètres qui déterminent exactement ce que la méthode fait). Dans ce cas, les surcharges vous permettent de spécifier n'importe quel ensemble de paramètres que vous pouvez passer à un autre processus quand il démarre. Ce que vous pouvez faire avec Process. Start n'est vraiment limité que par les processus que vous pouvez utiliser avec elle. Continuer à lire ci-dessous Qui est-à-dire, il n'y a aucune limite puisque plus continuer à venir tout le temps. Si vous voulez afficher votre fichier texte 34ReadMe34 dans le Bloc-notes, il est aussi simple que: Cela suppose que le fichier ReadMe se trouve dans le même dossier que le programme et que Notepad est l'application par défaut pour les types de fichiers. txt et it39s dans l'environnement système chemin. Pour les VB639ers dans le public, Process. Start est un peu comme la commande VB6 Shell. Dans VB6, vous pouvez utiliser quelque chose comme: lngPID 61 Shell (34MyTextFile. txt34, vbNormalFocus) Vous pouvez toujours appeler la commande Shell dans VB. NET, mais je wouldn39t le recommander. Utilisez Process. Start à la place. Vous pouvez utiliser ce code à la place pour démarrer le bloc-notes maximisé et créer un objet ProcessStartInfo que vous pouvez utiliser pour un contrôle plus précis: Dim ProcessProperties As New ProcessStartInfo ProcessProperties. FileName 64 34notepad34 ProcessProperties. Arguments 61 34myTextFile. txt34 ProcessProperties. WindowStyle 61 ProcessWindowStyle. Maximized Dim myProcess Process ProcessStart (ProcessProperties) Continuer la lecture ci-dessous Vous pouvez même démarrer un processus masqué. ProcessProperties. WindowStyle 61 ProcessWindowStyle. Hidden Mais soyez prudent. Sauf si vous ajoutez plus de code pour terminer le processus, vous devrez probablement le terminer dans le Gestionnaire des tâches. Les processus cachés ne sont normalement utilisés qu'avec des processus qui ne possèdent aucune interface utilisateur. Travailler avec Process. Start en tant qu'objet. NET vous donne beaucoup de possibilités. Par exemple, vous pouvez récupérer le nom du processus qui a été démarré. Ce code affichera 34notepad34 dans la fenêtre Sortie: Dim myProcess As Process 61 Process. Start (34MyTextFile. txt34) Console. WriteLine (myProcess. ProcessName) Si vous devez suspendre l'exécution de votre programme jusqu'à ce que le processus soit terminé (quelque chose que vous pourriez faire Avec le code API dans VB6), voilà. Console. WriteLine (34Notepad terminé: 34 amp myProcess. ExitTime amp Environment. NewLine amp 34Exit Code: 34 amp myProcess. ExitCode) Cela était quelque chose que vous ne pouviez pas faire avec la commande VB6 Shell, car il a lancé la nouvelle application de façon asynchrone. L'utilisation de WaitForExit peut provoquer le problème inverse dans. NET parce que vous devez lancer un processus dans un nouveau thread si vous en avez besoin pour exécuter de façon asynchrone. Par exemple, si vous avez besoin que les composants restent actifs dans une forme où un processus a été lancé et WaitForExit a été exécuté. Habituellement, ces composants ne seront pas actifs. Code it up et de voir par vous-même. Une méthode pour forcer le processus à arrêter est d'utiliser la méthode Kill. Ce code attend 10 secondes, puis termine le processus. J'ai constaté qu'un délai forcé était nécessaire pour permettre au processus de se terminer pour éviter une erreur. MyProcess. WaitForExit (10000) 39 si le processus ne s'achève pas dans 39 10 secondes, tuez-le Si non myProcess. HasExited Puis myProcess. Kill () End If Threading. Thread. Sleep (1) Console. WriteLine (34Notepad terminé: 34 amp myProcess. ExitTime amp Environment. NewLine amp 34Exit Code: 34 amp myProcess. ExitCode) Dans la plupart des cas, il est probablement une bonne idée de mettre votre traitement dans un bloc d'utilisation pour s'assurer que les ressources utilisées par le processus sont libérées. Utilisation de myProcess As Process 61 Nouveau processus 39 Votre code est utilisé ici Fin Utilisation Pour rendre tout cela encore plus facile à utiliser, il ya même un composant Process que vous pouvez ajouter à votre projet afin que vous puissiez faire beaucoup de choses ci-dessus à la conception Temps au lieu du temps d'exécution. Une des choses que cela rend beaucoup plus facile est de coder les événements soulevés par le processus, comme l'événement lorsque le processus a quitté. Vous pouvez également ajouter un gestionnaire en utilisant un code comme celui-ci. 39 autoriser le processus à émettre des événements myProcess. EnableRaisingEvents 61 True 39 ajouter un gestionnaire d'événements Exited AddHandler myProcess. Exited, AddressOf Me. ProcessExited Private Sub ProcessExited (ByVal expéditeur comme Object, ByVal e As System. EventArgs) 39 Votre code va ici End Sub Mais la simple sélection de l'événement pour le composant est beaucoup plus facile.


No comments:

Post a Comment