2009-02-10 3 views
0

Je dois utiliser une API pour appeler un tiers et, idéalement, utiliser la réponse qu'elle renvoie. L'API dispose d'un délai d'attente intégré de 30 secondes et ne vous permet pas de le définir par programmation. J'en ai besoin pour expirer en 12 secondes. Voici l'appel que je fais:Comment puis-je imposer mon propre délai d'expiration?

réponse de chaîne = theAPI.FunctionA (a, b, c, d);

J'ai pensé que j'aurais besoin d'utiliser des appels asynchrones pour accomplir ceci et abandonner le thread à 12 secondes. Une autre question de stackoverflow semble se rapprocher de ce que je considère: Implement C# Generic Timeout

... Je me demande simplement si c'est la meilleure façon. Spécifiquement, je continue à voir des articles qui vous avertissent d'appeler EndInvoke n'importe quoi, et je me demande si Abort comme dans l'exemple référencé fermera toujours le thread de manière appropriée? Je vois qu'il y avait quelques commentaires avec beaucoup d'inquiétude concernant l'utilisation d'Abort.

Répondre

4

L'annulation de threads est généralement une mauvaise idée. Pourquoi ne pas laisser l'appel se terminer (ou expirer après 30 secondes) mais ignorer le résultat (et passer à autre chose) si cela prend plus de 12 secondes?

+0

Le deal est à 12 secondes, j'ai besoin de renflouer et de passer à autre chose.Je ne peux pas m'asseoir et attendre les 30 secondes entières. Si on me permettait de le laisser fonctionner pendant les 30 secondes, j'irais certainement de cette façon. – Chad

+0

Je ne suggérais pas d'attendre 30 secondes. Notez le "ignorez le résultat (et continuez) si cela prend plus de 12 secondes" bit. Tout ce que je suggère, c'est que votre délai ne devrait pas tuer la demande. Laissez-le compléter naturellement, pendant que vous continuez avec d'autres choses. –

+0

Ok, je pense que je te suis. Je ferais peut-être un appel asynchrone avec une fonction de rappel attendant que les choses se terminent. Pendant ce temps mon code passe, et si je n'ai pas encore de réponse après 12 secondes, je continue comme s'il y avait un timeout. Ma fonction de rappel ne fait rien si plus de 12 secondes. – Chad

2

Thread.Abort fermera le fil, bien sûr, car il appellera Win32 TerminateThread.

Le résultat de cette action dépendra de la façon dont votre API aime être fermé par TerminateThread.

Si votre méthode s'appelle quelque chose comme NuclearPlant.MoveRod() ou Defibrillator.Shock(), je préfère attendre ces 30 secondes.

Cette méthode donne aucune chance à la victime de faire un nettoyage:

TerminateThread est utilisé pour faire un fil pour sortir. Lorsque cela se produit, le thread cible n'a aucune chance d'exécuter un code en mode utilisateur. Les DLL attachées au thread ne sont pas averties que le thread se termine. Le système libère la pile initiale du thread.

Comme indiqué dans MSDN:

TerminateThread est une fonction dangereuse qui ne doit être utilisé dans les cas les plus extrêmes. Vous devez appeler TerminateThread uniquement si vous savez exactement ce que fait le thread cible et que vous contrôlez tout le code que le thread cible pourrait éventuellement exécuter au moment de la terminaison. Par exemple, TerminateThread peut entraîner les problèmes suivants:

  • Si le thread cible possède une section critique, la section critique ne sera pas libérée.
  • Si le thread cible alloue de la mémoire à partir du tas, le verrou de tas ne sera pas libéré.
  • Si le thread cible exécute certains appels kernel32 lorsqu'il est terminé, l'état kernel32 du processus du thread peut être incohérent.
  • Si le thread cible manipule l'état global d'une DLL partagée, l'état de la DLL peut être détruit, affectant d'autres utilisateurs de la DLL.
+0

On dirait que vous ne vous sentez pas faire un Abort est une idée sûre, et je peux voir pourquoi par vos commentaires. Donc, si Abort est quelque chose à éviter, avez-vous une solution alternative? – Chad

+0

Si votre API n'a aucun moyen d'arrêter la méthode, il n'y a pas de solution alternative. Toutes ces solutions, le cas échéant, reposent sur la capacité du thread à réagir aux signaux externes et à agir de manière appropriée. Si le thread ne le fait pas, TerminateThread est le seul moyen de l'arrêter. – Quassnoi