J'ai des System.Diagnotics.Processes à exécuter. Je voudrais appeler la méthode de fermeture sur eux automatiquement. Apparemment, le mot-clé "using" fait cela pour moi. Est-ce la façon d'utiliser le mot-clé using? Je voudrais démarrer plusieurs processus pour exécuter simultanément.Comment utiliser par programme le mot-clé "using" en C#?
Répondre
using(p = Process.Start(command))
Cela compilera, comme la classe Process
implémente IDisposable
, mais vous voulez vraiment appeler la méthode Close
.
Logique voudrait que la méthode Dispose
appelle Close
pour vous, et en creusant dans le CLR en utilisant le réflecteur, nous pouvons voir que cela fait en fait pour nous. Jusqu'ici tout va bien.
Toujours en utilisant le réflecteur, j'ai regardé ce que la méthode Close
fait - il libère le handle de processus natif win32 sous-jacent, et efface certaines variables membres. Ceci (libérant des ressources externes) est exactement ce que le modèle IDisposable est censé faire.
Cependant Je ne sais pas si c'est ce que vous voulez réaliser ici. Relâcher les poignées sous-jacentes indique simplement aux fenêtres «Je ne suis plus intéressé par le suivi de cet autre processus». À aucun moment, cela n'entraîne l'arrêt de l'autre processus ou l'attente de votre processus.
Si vous voulez les forcer à quitter, vous devez utiliser la méthode p.Kill()
sur les processus - cependant, il est conseillé de ne pas tuer les processus car ils ne peuvent pas nettoyer après eux-mêmes, et peuvent laisser derrière des fichiers corrompus, et ainsi de suite.
Si vous voulez attendre qu'ils quittent d'eux-mêmes, vous pouvez utiliser p.WaitForExit()
- mais cela ne fonctionnera que si vous attendez un processus à la fois. Si vous voulez les attendre tous simultanément, cela devient compliqué.
Normalement vous utilisez WaitHandle.WaitAll
pour cela, mais comme il n'y a pas moyen d'obtenir un objet WaitHandle
d'un System.Diagnostics.Process
, vous ne pouvez pas le faire (sérieusement, wtf songeaient microsoft?).
Vous pouvez créer un thread pour chaque processus et appeler `WaitForExit dans ces threads, mais c'est également la mauvaise façon de le faire.
Vous devez utiliser p/invoke pour accéder à la fonction natif win32 WaitForMultipleObjects
.
Voici un échantillon (que je l'ai testé et fonctionne réellement)
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
static extern uint WaitForMultipleObjects(uint nCount, IntPtr[] lpHandles, bool bWaitAll, uint dwMilliseconds);
static void Main(string[] args)
{
var procs = new Process[] {
Process.Start(@"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 2'"),
Process.Start(@"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 3'"),
Process.Start(@"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 4'") };
// all started asynchronously in the background
var handles = procs.Select(p => p.Handle).ToArray();
WaitForMultipleObjects((uint)handles.Length, handles, true, uint.MaxValue); // uint.maxvalue waits forever
}
try
{
foreach(string command in S) // command is something like "c:\a.exe"
{
using(p = Process.Start(command))
{
// I literally put nothing in here.
}
}
}
catch (Exception e)
{
// notify of process failure
}
La raison pour laquelle cela fonctionne est parce que quand l'exception se produit, la variable p tombe hors de portée et donc sa méthode Dispose est appelée qui ferme le processus est de savoir comment cela irait. De plus, je pense que vous voudriez faire tourner un thread pour chaque commande plutôt que d'attendre qu'un exécutable finisse avant de passer au suivant.
Pour référence: Le utilise mot-clé pour IDisposable objets:
using(Writer writer = new Writer())
{
writer.Write("Hello");
}
est juste compilateur syntaxe. Ce qu'il compile à est:
Writer writer = null;
try
{
writer = new Writer();
writer.Write("Hello");
}
finally
{
if(writer != null)
{
((IDisposable)writer).Dispose();
}
}
using
est un peu mieux depuis le compilateur vous empêche de réattribuer la référence écrivain à l'intérieur du bloc à l'aide.
Les directives-cadres Section 9.3.1 p. 256 état:
EXAMINER fournissant méthode Close(), en plus de l'Dispose(), si proche est terminologie standard dans le domaine.
Dans votre exemple de code, le try-catch externe est inutile (voir ci-dessus). L'utilisation probablement ne fait pas ce que vous voulez ici puisque Dispose() est appelé dès que p
sort de la portée. Cela ne ferme pas le processus (testé).
Les processus sont indépendants, donc à moins que vous n'appelez p.WaitForExit()
ils essaient de faire leur propre chose complètement indépendant de votre programme.
Contre-intuitif, pour un processus, Close() libère uniquement des ressources mais laisse le programme en cours d'exécution. CloseMainWindow() peut fonctionner pour certains processus, et Kill() fonctionnera pour tuer n'importe quel processus. CloseMainWindow() et Kill() peuvent toutes deux lever des exceptions, donc faites attention si vous les utilisez dans un bloc finally. Pour finir, voici un code qui attend que les processus se terminent mais ne tue pas les processus lorsqu'une exception se produit. Je ne dis pas que c'est mieux qu'Orion Edwards, juste différent. Je n'ai pas dérangé Kill() à cause des processus parce que le code commence à être encore plus laid. Lisez la documentation msdn pour plus d'informations.
- 1. génération de code par programme en C# using codedom
- 2. Comment invoquer le compilateur C++ par programme?
- 3. Comment utiliser Netbeans Profiler par programme?
- 4. C# Comment modifier le périphérique de lecture par programme
- 5. Exporter le contrôle Reportviewer C# par programme
- 6. Modifier le clavier par programme en Dvorak
- 7. Comment analyser par programme et modifier le code C#
- 8. Redémarrer par programme IIS7 (C#)
- 9. Comment fermer par programme un formulaire InfoPath en C#?
- 10. Comment utiliser les services de terminal par programme
- 11. comment localiser un programme sur le bureau par C#
- 12. Dois-je utiliser "using" sur mon SitkaSoapServiceClient?
- 13. Comment puis-je exécuter par programme le serveur de développement ASP.Net en utilisant C#?
- 14. Télécharger le JRE par programme?
- 15. WinApp en C# appelant le programme java
- 16. Utiliser par programme les loaddata de Django
- 17. Comment activer le programme Wake on LAN par programme
- 18. Comment exécuter NUnit par programme
- 19. Comment utiliser genshi.builder pour créer par programme un document HTML?
- 20. C# - Comment peupler un .net DataGridView par programme?
- 21. Le php imbriqué inclut using './'
- 22. Ajout par programme d'autorisations de sécurité aux fichiers en C#
- 23. C# Comment onglet par programme entre les contrôles
- 24. Comment utiliser StreamReader en C# (débutant)
- 25. Comment utiliser EmguCV (OpenCV en C#)?
- 26. Comment utiliser ArrayList en C++?
- 27. Comment utiliser COM en C#
- 28. Quand utiliser avec (...) {...} en C#?
- 29. comment utiliser XMLRPC en C#
- 30. Comment utiliser WM_Close en C#?