Commande de thread à l’aide de ThreadPool.QueueUserWorkItem

Je suis novice dans les bases du threading.

J’ai une queue d’opérations à effectuer sur des fichiers XML (ajout de nœud, suppression de nœud, etc.)

1] Il existe des fichiers ‘n’ xml et pour chaque fichier, un thread du pool de threads est alloué à l’aide de ThreadPool.QueueUserWorkItem pour effectuer ces opérations de fichier.

Je veux réaliser à la fois la simultanéité et la commande d’opération (important) à l’aide de threads.
Exemple: Supposons que les opérations [a1, a2, a3, a4, a5] doivent être effectuées dans le fichier “A.xml”
et les opérations [b1, b2, b3, b4, b5, b6, b7] doivent être effectuées dans le fichier “B.xml” …..
Je veux allouer des fils tels que je puisse effectuer ces opérations dans le
même ordre et aussi simultanément (puisque les fichiers sont différents).

2] Il est également possible d’atsortingbuer un fil à chaque opération, d’assurer la concurence et de préserver l’ordre.

Dans le modèle STA, j’ai fait quelque chose de similaire.

while(queue.count>0){ File f = queue.Dequeue(); //get File from queue OperationList oprlst = getOperationsForFile(f); // will get list-> [a1,a2,a3,a4,a5] for each Operation oprn in oprlst { performOperation(f,oprn) //in MTA i want to wait till operation "a1" completes and then operation "a2" will //start.making threads wait till file is in use or operation a(i) is in use. } } 

Je veux le faire en même temps que la préservation de l’ordre d’opération. Les threads (de l’opération) peuvent attendre un fichier … mais différentes opérations prennent des temps d’exécution différents.

J’ai essayé AutoResetEvent et WaitHandle.WaitAll (..), mais la boucle while s’est arrêtée jusqu’à la fin de toutes les opérations ‘a (i)’. (mais en commandant en a (i) et b (j))

Utilise actuellement .net 2.0.

Ceci est assez similaire et fait partie de cette question posée Question

Évitez d’utiliser des techniques de blocage de threads telles que les verrous du Monitor et les structures ThreadPool dans les threads ThreadPool , car ces threads sont utilisés par d’autres processus. Votre thread doit être basé sur des fichiers individuels. Si un fichier individuel ne prend pas beaucoup de temps à traiter (et que vous n’avez pas trop de fichiers), alors le ThreadPool fonctionnera.

Implémentation ThreadPool

Vous pouvez simplement utiliser EnqueueUserWorkItem sur une méthode centrée sur le fichier … quelque chose comme ceci:

 private void ProcessFile(Object data) { File f = (File)data; foreach(Operation oprn in getOperationsForFile(f)) { performOperation(f, oprn); } } 

Ensuite, dans votre code qui traite les fichiers, procédez comme suit:

 while(queue.Count > 0) { ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessFile), queue.Dequeue()); } 

Si vous avez besoin que votre thread appelant bloque jusqu’à ce qu’ils soient tous terminés, un WaitHandle est OK (puisque vous WaitHandle votre propre thread, pas le thread ThreadPool ). Cependant, vous devrez créer une petite classe de charge utile pour la passer au thread:

 private class Payload { public File File; public AutoResetEvent Handle; } private void ProcessFile(Object data) { Payload p = (Payload)data; foreach(Operation oprn in getOperationsForFile(p.File)) { performOperation(f, oprn); } p.Handle.Set(); } ... WaitHandle[] handles = new WaitHandle[queue.Count]; int index = 0; while(queue.Count > 0) { handles[index] = new AutoResetEvent(); Payload p = new Payload(); p.File = queue.Dequeue(); p.Handle = handles[index]; ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessFile), p); index++; } WaitHandle.WaitAll(handles); 

Implémentation de fil

Si, toutefois, vous avez un grand nombre de fichiers (ou que le traitement de vos fichiers peut prendre beaucoup de temps), la création de vos propres threads est une meilleure idée. Cela vous permet également d’omettre l’ WaitHandle .

 private void ProcessFile(File f) { foreach(Operation oprn in getOperationsForFile(f)) { performOperation(f, oprn); } p.Handle.Set(); } private object queueLock = new object(); private void ThreadProc() { bool okToContinue = true; while(okToContinue) { File f = null; lock(queueLock) { if(queue.Count > 0) { f = queue.Dequeue(); } else { f = null; } } if(f != null) { ProcessFile(f); } else { okToContinue = false; } } } ... Thread[] threads = new Thread[20]; // arbitrary number, choose the size that works for(int i = 0; i < threads.Length; i++) { threads[i] = new Thread(new ThreadStart(ThreadProc)); thread[i].Start(); } //if you need to wait for them to complete, then use the following loop: for(int i = 0; i < threads.Length; i++) { threads[i].Join(); } 

L'exemple précédent est un pool de threads très rudimentaire, mais il devrait illustrer ce qui doit être fait.

Créez un nouveau thread pour chaque fichier ou utilisez simplement un ThreadPool.QueueUserWorkItem appel ThreadPool.QueueUserWorkItem pour chaque fichier. De toute façon, vous souhaitez que les opérations du fichier soient exécutées séquentiellement dans l’ordre. Dans votre cas, le seul parallélisme disponible concerne différents fichiers, et non des opérations.

Les threads sont destinés aux opérations pouvant être effectuées de manière asynchrone et vous voulez que vos opérations soient effectuées de manière synchrone. Le traitement des fichiers semble cependant pouvoir être effectué de manière asynchrone (multithread).