Comment tuer un fil C #?

J’ai un fil qui sort et cherche des données sur notre (ancien) serveur SQL.

Au fur et à mesure que les données arrivent, j’envoie des informations dans une boîte de dialog modale: l’utilisateur ne peut pas et ne devrait rien faire d’autre pendant tout le traitement en cours. La boîte de dialog modale sert simplement à leur faire savoir que je fais quelque chose et à les empêcher de lancer une autre requête en même temps.

Parfois (rarement) lorsque le code appelle le serveur SQL, le serveur ne répond pas (le service informatique le met hors service pour maintenance, la ligne LAN a été coupée ou le PC n’est pas sur le réseau) ou la personne qui effectue la requête manque de temps. Donc, la boîte de dialog modale a un bouton Annuler.

L’object Thread (System.Threading.Thread) a IsBackground=true .

Lorsque quelqu’un clique sur Annuler, j’appelle ma méthode KillThread .

Remarque: Je ne peux PAS utiliser le composant BackgroundWorker dans cette classe car il est partagé avec du code Windows Mobile 5 et que WM5 n’a pas le BackgroundWorker.

 void KillThread(Thread th) { if (th != null) { ManualResetEvent mre = new ManualResetEvent(false); Thread thread1 = new Thread( () => { try { if (th.IsAlive) { //th.Stop(); // 'System.Threading.Thread' does not contain a definition for 'Stop' // and no extension method 'Stop' accepting a first argument of type // 'System.Threading.Thread' could be found (are you missing a using // directive or an assembly reference?) th.Abort(); } } catch (Exception err) { Console.WriteLine(err); } finally { mre.Set(); } } ); ssortingng text = "Thread Killer"; thread1.IsBackground = true; thread1.Name = text; thread1.Start(); bool worked = mre.WaitOne(1000); if (!worked) { Console.WriteLine(text + " Failed"); } th = null; } } 

Dans ma fenêtre de sortie, je vois toujours “Thread Killer Failed” mais aucune exception n’a été levée.

Comment dois-je arrêter un fil?

Les meilleurs articles liés que j’ai trouvés où les deux ci-dessous:

Comment tuer le fil en C #?
Comment tuer un fil instantanément en C #?

MODIFIER:

Il semble y avoir une certaine confusion avec la méthode que j’ai énumérée ci-dessus.

Premièrement, lorsque quelqu’un clique sur le bouton d’annulation, cette routine s’appelle:

 void Cancel_Click(object sender, EventArgs e) { KillThread(myThread); } 

Ensuite, lorsque je vais tuer un fil, je préférerais ne pas attendre indéfiniment que le fil s’arrête. En même temps, je ne veux pas laisser mon code continuer si le thread est toujours actif. Donc, j’utilise un object ManualResetEvent . Cela ne devrait pas prendre une seconde complète (1000 ms) juste pour arrêter un thread, mais à chaque fois que la méthode WaitOne .

Toujours à l’écoute des idées.

Réponse courte: vous ne le faites pas. Normalement, vous le faites en indiquant que vous souhaitez quitter. Si vous lancez une requête SQL, procédez de manière asynchrone (excusez mon orthographe) et annulez-la si nécessaire. Cela vaut vraiment pour toute tâche longue dans un fil séparé.

Pour en savoir plus, consultez les articles d’Eric Lippert: Attention à la hache, première partie: dois-je spécifier un délai d’attente? et Attention avec cette hache, deuxième partie: Qu’en est-il des exceptions?

Edit: Comment appelez-vous SQL Server? ADO, TDS, bibliothèque standard / personnalisée, etc …? Cet appel devrait être fait en asynchrone. Ainsi: StartOpeningConnection, WaitFor OpeningComplete, StartQuery, WaitFor QueryComplete, Start CloseConnection, WaitFor CloseConnectionComplete, etc. Pendant toute attente, votre thread doit dormir. Après le réveil, vérifiez si votre thread parent (le thread d’interface utilisateur) a été annulé ou si un délai a expiré, quittez le thread et informez éventuellement sqlserver que vous avez terminé (fermeture de la connexion).

Ce n’est pas facile, mais ça l’est rarement …

Edit 2 : Dans votre cas, si vous ne pouvez pas modifier le code de la firebase database en asynchrone, faites-en un processus séparé et supprimez-le si nécessaire. Ainsi, les ressources (connexion, etc.) seront libérées. Avec les discussions, ce ne sera pas le cas. Mais c’est un bidon moche .

Édition 3: vous devez utiliser le modèle BeginExecuteReader / EndExecuteReader. Cet article est une bonne référence: il vous faudra réécrire votre code d’access aux données, mais c’est le moyen de le faire correctement.

J’ai le sentiment que donner le fil 1000 ms à avorter n’est tout simplement pas suffisant. MSDN vous recommande d’appeler Thread.Join. Il serait certainement utile de voir le code en cours d’abandon.

Thread.Abort

Il n’est pas garanti que le thread abandonne immédiatement, ni même du tout. Cette situation peut se produire si un thread effectue un nombre illimité de calculs dans les derniers blocs appelés dans le cadre de la procédure d’abandon, retardant ainsi indéfiniment l’abandon. Pour attendre l’abandon d’un thread, vous pouvez appeler la méthode Join sur le thread après avoir appelé la méthode Abort, mais rien ne garantit que l’attente se terminera.

Que passez-vous dans votre méthode KillThread ? Le bouton Annuler sera cliqué sur le fil de l’interface utilisateur, pas celui que vous souhaitez tuer.

Vous devez signaler votre événement lorsque l’utilisateur clique sur Annuler (ne tue pas le fil). Dans votre exemple, la scope de “mre” de ManualResetEvent doit être en dehors de la fonction thread.