2010-04-02 3 views
0

J'ai une application web qui exécute plusieurs threads sur le bouton, cliquez sur chaque thread faisant appel IO sur différentes adresses ip, c'est à dire (compte Windows de connexion, puis faire des opérations de fichiers). Il y a une valeur de seuil de 30 secondes. Je suppose que lors de la tentative de connexion si le seuil est dépassé, le périphérique sur ipAddress ne correspond pas à mes conditions, donc je m'en fous. Thread.Abort() ne correspond pas à ma situation où il attend que l'appel d'E/S finisse, ce qui peut prendre beaucoup de temps.Problème avec les threads non répondeurs

J'ai essayé de faire les opérations db selon les états des threads juste après le délai d'attente. Cela a fonctionné correctement mais lorsque j'ai vérifié le fichier journal, j'ai remarqué que la propriété thread.IsAlive des threads non répondants était toujours vraie. Après plusieurs débogages sur mon PC local, j'ai rencontré une situation de blocage possible (ce que je soupçonne) que mon PC s'est brisé mal. En bref, avez-vous une idée sur la destruction (avec force) des threads non répondeurs (en attente de l'opration IO) juste aprs l'excution du bouton button_click?

(PS: Je ne suis pas en utilisant le threadpool)

Oguzhan

EDIT

Pour plus de précisions,

Je dois valider les informations d'identification d'administrateur local données sur chaque ipAddress, et insérer l'enregistrement DB pour les successifs. Le reste, je m'en fous.

Dans ma méthode de validation, j'ai d'abord lancé un appel à la méthode logonuser de win32 en important advapi32.dll pour usurper l'identité de l'utilisateur administrateur. Après cela, je attampt pour créer un répertoire temp sur le lecteur sys distant via la méthode Directory.CreateDirectory juste pour vérifier l'autorisation. Si une exception a été levée (UnauthorizedAccessException ou IOException), la machine distante est hors d'intérêt, sinon nous l'avons insérée dans DB.

J'ai appelé la méthode de validation façon synchrone pour une plage IP donnée et cela a bien fonctionné pour un tas de points de terminaison successifs. Mais lorsque j'ai testé la méthode pour une plage ipAddress non pertinente, chaque tentative de validation a duré de 20 secondes à 5 minutes. J'ai ensuite transformé mon design en mode multithread dans lequel j'ai décidé d'exécuter chaque validation dans un thread séparé et d'abandonner les threads qui ne répondaient pas à la fin de la valeur de seuil. Le problème était que le thread.abort ne convenait pas bien à la situation, ce qui en fait attend le retour de l'instruction IO (ce que je ne veux pas) et déclenche une exception ThreadAbortException après cela. Pour terminer l'exécution des threads successifs, j'ai ignoré les threads non-répondants et poursuivi les opérations DB et revenez de la méthode du clic de bouton (les thrings non-répondants étaient encore vivants à ce moment-là). Tout s'est bien passé jusqu'à ce que je reçoive un crash système après l'exécution du clic (en mode debug) à plusieurs reprises. Le problème était probablement le nombre croissant de fils vivants sous le service d'IIS.

SOLUTION

cause des fils de ne pas répondre en temps opportun est le chemin réseau ne la situation pas trouvé. Ma solution est de vérifier la connectivité via TCP sur le port 135 (le port 135 est obligatoire pour RPC sur Windows) avant de faire l'appel d'E/S. La période d'expiration par défaut est de 20 secondes. Si vous devez définir le délai, utilisez BeginConenct. Une autre option serait Pinging (si ICMP est activé dans le réseau)

+1

La question évidente ici est: * pourquoi * faites-vous cela avec plusieurs threads à partir d'un événement de clic de bouton? Y at-il une raison pour laquelle vous ne pouvez pas simplement exécuter les méthodes dont vous avez besoin pour exécuter l'une après l'autre? – MusiGenesis

+0

Plus de détails nécessaires: quel est l'appel qui prend du temps? Est-ce que Socket est en lecture/écriture? Est-ce ...? – Gonzalo

Répondre

2

Pourquoi avez-vous vraiment besoin d'annuler les threads de toute façon?Pourquoi ne pas les laisser compléter normalement mais ignorer les résultats? (Conservez un jeton pour indiquer le «lot» de demandes dans lequel il se trouve, puis rappelez-vous quel lot vous intéresse réellement pour le moment.)

Une autre option consiste à conserver ce que vous utilisez pour faire un Appel d'E/S (par exemple une prise) et fermez-le; cela devrait provoquer une exception sur le thread faisant la demande. Encore une autre option est d'éviter de placer les requêtes sur des threads différents, mais d'utiliser des E/S asynchrones - vous obtiendrez toujours le parallélisme, mais sans attacher les threads (juste des ports d'achèvement IO). En outre, ne pouvez-vous pas mettre un délai d'attente sur l'opération d'E/S elle-même? La demande devrait juste expirer naturellement de cette façon.

+0

+ 1 pour mettre le "timeout sur l'opération d'E/S", mais vous le saviez déjà. –

+0

Merci pour la réponse, j'ai mis quelques informations supplémentaires dans ma réponse ci-dessous. Existe-t-il un moyen de valider l'utilisateur administrateur local via IO asynchrone? Comme je l'ai dit plus bas, j'utilise l'emprunt d'identité et le répertoire créé (que je qualifie d'IO) pour valider. Ou comment mettre timeout sur la méthode de répertoire créé? – Oxygen

+0

@Oxygen: Je crains que cela ne ressemble pas à la création de répertoire prend en charge un délai d'attente ... ce n'est pas vraiment une API orientée réseau :( –

Questions connexes