Visual Studio: ContextSwitchDeadlock

167

J'ai reçu un message d'erreur que je ne peux pas résoudre. Il provient de Visual Studio ou du débogueur. Je ne sais pas si la condition d'erreur ultime se trouve dans VS, le débogueur, mon programme ou la base de données.

Ceci est une application Windows. Pas une application Web.

Le premier message de VS est une fenêtre contextuelle disant: "Aucun symbole n'est chargé pour aucune trame de pile d'appels. Le code source ne peut pas être affiché." Quand cela est cliqué, j'obtiens: " ContextSwitchDeadlock a été détecté ", avec un long message reproduit ci-dessous.

L'erreur survient dans une boucle qui analyse un DataTable. Pour chaque ligne, il utilise une valeur de clé (HIC #) de la table comme paramètre pour un SqlCommand. La commande est utilisée pour créer un SqlDataReader qui renvoie une ligne. Les données sont comparées. Si une erreur est détectée, une ligne est ajoutée à un deuxième DataTable.

L'erreur semble être liée à la durée d'exécution de la procédure (c'est-à-dire au bout de 60 secondes) et non au nombre d'erreurs trouvées. Je ne pense pas que ce soit un problème de mémoire. Aucune variable n'est déclarée dans la boucle. Les seuls objets créés sont les SqlDataReaders, et ils se trouvent dans Using structures. Ajouter System.GC.Collect () n'a eu aucun effet.

La base de données est un site SqlServer sur le même ordinateur portable.

Il n'y a pas de gadgets ou gadgets sophistiqués sur le formulaire.

Je ne suis au courant de rien dans ce processus qui soit très différent de ce que j'ai fait des dizaines de fois auparavant. J'ai déjà vu l'erreur, mais jamais de manière cohérente.

Des idées, quelqu'un?

Texte d'erreur complet: le CLR n'a pas pu passer du contexte COM 0x1a0b88 au contexte COM 0x1a0cf8 pendant 60 secondes. Le thread qui possède le contexte / cloisonnement de destination est très probablement en train de faire une attente sans pompage ou de traiter une opération très longue sans pompage de messages Windows. Cette situation a généralement un impact négatif sur les performances et peut même conduire l'application à devenir non réactive ou l'utilisation de la mémoire s'accumulant continuellement au fil du temps. Pour éviter ce problème, tous les threads STA (single threaded apartment) doivent utiliser des primitives d'attente de pompage (telles que CoWaitForMultipleHandles) et pomper régulièrement des messages pendant les opérations de longue durée.

SeaDrive
la source

Réponses:

287

Le ContextSwitchDeadlockne signifie pas nécessairement votre code a un problème, juste qu'il ya un potentiel. Si vous allez Debug > Exceptionsdans le menu et développez le Managed Debugging Assistants, vous trouverez ContextSwitchDeadlockest activé. Si vous désactivez cette option, VS ne vous avertira plus lorsque les éléments prennent beaucoup de temps à traiter. Dans certains cas, vous pouvez valablement avoir une opération de longue durée. C'est également utile si vous déboguez et que vous vous êtes arrêté sur une ligne pendant le traitement - vous ne voulez pas qu'il se plaigne avant d'avoir eu l'occasion de creuser un problème.

Pedro
la source
4
Droit dessus! Merci. J'ai dû aller dans Personnaliser et ajouter des exceptions au menu Déboguer. Ce n'est pas l'aspect le plus intuitif de l'interface utilisateur. Outils \ Personnaliser, puis Réorganiser les commandes (bouton), puis Sélectionnez Déboguer dans la liste déroulante en haut à droite, puis Ajouter (bouton). Ouf!
SeaDrive
81
ctrl-alt-eapporte la boîte de dialogue d'exception.
Florian Doyon
1
De nombreuses versions les plus récentes de Visual Studio (2012, 2010, 2008) et peut-être certaines versions antérieures, permettent de choisir l'utilisation principale de Visual Studio lors de sa première exécution après l'installation. Ce choix détermine la disposition par défaut des barres d'outils, y compris les contrôles visibles ou masqués et même les frappes correspondant à quelles commandes. Dans VS 2010, l'assistant d'importation et d'exportation des paramètres vous permet de réinitialiser l'un des paramètres par défaut disponibles.
Zarepheth
4
@ B.ClayShannon - ContextSwitchDeadlock est spécifique au débogueur. Une version commerciale de l'exe n'affichera pas ce message.
Pedro
9
Dans VS 2013, naviguez avec Debug -> Windows -> Exceptions Settings. Ensuite, utilisez la recherche
Markus Weber
16

Comme l'a dit Pedro, vous avez un problème avec le débogueur qui empêche la pompe de message si vous parcourez le code.

Mais si vous effectuez une opération de longue durée sur le thread d'interface utilisateur, appelez Application.DoEvents () qui pompe explicitement la file d'attente de messages, puis retourne le contrôle à votre méthode actuelle.

Cependant, si vous faites cela, je vous recommanderais de regarder votre conception afin que vous puissiez effectuer le traitement hors du fil de l'interface utilisateur afin que votre interface utilisateur reste agréable et vive.

Spence
la source
14

On dirait que vous faites cela sur le fil principal de l'interface utilisateur de l'application. Le thread d'interface utilisateur est responsable du pompage des messages Windows à l'arrivée, et pourtant, comme le vôtre est bloqué dans les appels de base de données, il ne peut pas le faire. Cela peut entraîner des problèmes avec les messages à l'échelle du système.

Vous devriez regarder la création d'un thread d'arrière-plan pour l'opération de longue durée et mettre en place une sorte de boîte de dialogue "Je suis occupé" pour l'utilisateur pendant que cela se produit.

Rob Walker
la source
13

Dans Visual Studio 2017, décochez l'option ContextSwitchDeadlock en:

Déboguer> Windows> Paramètres d'exception

entrez la description de l'image ici

Dans les paramètres d'exception Windows: décochez l'option ContextSwitchDeadlock

entrez la description de l'image ici

Hassan Rahman
la source
9

Si vous ne souhaitez pas désactiver cette exception, il vous suffit de laisser votre application pomper des messages au moins une fois toutes les 60 secondes. Cela empêchera cette exception de se produire. Essayez d'appeler System.Threading.Thread.CurrentThread.Join (10) de temps en temps. Il y a d'autres appels que vous pouvez faire pour laisser les messages pomper.


la source
Pouvez-vous expliquer pourquoi cela aide?
lance
Cela ne fonctionnera pas, j'ai une interface utilisateur de mise à jour en boucle et je reçois toujours le message d'erreur.
htm11h
1
Il n'est pas nécessaire d'utiliser une valeur de 10 millisecondes, en fait si vous avez l'intention de l'appeler de manière répétée dans une opération de longue durée, cela diminuera considérablement les performances globales (durée totale d'exécution). Passez-lui simplement zéro.
ElektroStudios
J'ai eu un problème similaire. J'ai trouvé que votre solution fonctionnait. Merci!
Sk Shahnawaz-ul Haque le
2

La solution ci-dessus est bonne dans certains scénarios, mais il existe un autre scénario dans lequel cela se produit lorsque vous effectuez des tests unitaires et que vous essayez de «déboguer les tests sélectionnés» à partir de l'Explorateur de tests lorsque votre solution n'est pas définie sur Déboguer.

Dans ce cas, vous devez modifier votre solution de Release ou tout autre paramètre défini sur Debug dans ce cas. Si tel est le problème, changer "ContextSwitchDeadlock" ne vous aidera pas vraiment.

J'ai manqué cela moi-même parce que le message d'erreur était si méchant que je n'ai pas vérifié la chose évidente qui était le paramètre de débogage!

Ewan
la source
1

Dans la version espagnole de Visual Studio 2017.

"Depurar" -> "Ventanas" -> "Configuración de Excepciones"

et recherchez "ContextSwitchDeadlock". Ensuite, décochez-le. Ou raccourci

Ctrl + D, E

Meilleur.

kahonmlg
la source
0

Vous pouvez résoudre ce problème en décochant les contexteswitchdeadlock de

Déboguer-> Exceptions ... -> Développer le nœud MDA -> décocher -> contexteswitchdeadlock

KR Akhil
la source
0

J'obtenais cette erreur et j'ai basculé les requêtes sur async (wait (...). ToListAsync ()). Tout va bien maintenant.

Dunwan
la source