Visual Studio: ContextSwitchDeadlock

167

Recibí un mensaje de error que no puedo resolver. Se origina en Visual Studio o el depurador. No estoy seguro de si la condición de error final está en VS, el depurador, mi programa o la base de datos.

Esta es una aplicación de Windows. No es una aplicación web.

El primer mensaje de VS es un cuadro emergente que dice: "No se cargan símbolos para ningún marco de la pila de llamadas. El código fuente no se puede mostrar". Cuando se hace clic, aparece : " Se detectó ContextSwitchDeadlock ", junto con un mensaje largo que se reproduce a continuación.

El error surge en un bucle que escanea una DataTable. Para cada línea, utiliza un valor clave (HIC #) de la tabla como parámetro para un SqlCommand. El comando se usa para crear un SqlDataReader que devuelve una línea. Los datos son comparados. Si se detecta un error, se agrega una fila a una segunda DataTable.

El error parece estar relacionado con el tiempo que tarda el procedimiento en ejecutarse (es decir, después de 60 segundos), no con cuántos errores se encuentran. No creo que sea un problema de memoria. No se declaran variables dentro del ciclo. Los únicos objetos que se crean son los SqlDataReaders, y están en Usar estructuras. Agregar System.GC.Collect () no tuvo ningún efecto.

El db es un sitio SqlServer en la misma computadora portátil.

No hay artilugios o artilugios sofisticados en el formulario.

No estoy al tanto de nada en este proceso que sea muy diferente de lo que he hecho docenas de veces antes. He visto el error antes, pero nunca de manera consistente.

Alguna idea, alguien?

Texto de error completo: el CLR no ha podido realizar la transición del contexto COM 0x1a0b88 al contexto COM 0x1a0cf8 durante 60 segundos. El subproceso que posee el contexto / apartamento de destino probablemente esté haciendo una espera sin bombeo o procesando una operación de ejecución muy larga sin bombear mensajes de Windows. Esta situación generalmente tiene un impacto negativo en el rendimiento e incluso puede hacer que la aplicación deje de responder o que el uso de memoria se acumule continuamente con el tiempo. Para evitar este problema, todos los subprocesos de apartamento de un solo subproceso (STA) deben usar primitivas de espera de bombeo (como CoWaitForMultipleHandles) y mensajes de bombeo rutinarios durante operaciones de larga ejecución.

SeaDrive
fuente

Respuestas:

287

El ContextSwitchDeadlockno necesariamente significa que su código tiene un problema, solo que existe un potencial. Si va al Debug > Exceptionsmenú y expande Managed Debugging Assistants, encontrará que ContextSwitchDeadlockestá habilitado. Si deshabilita esto, VS ya no le avisará cuando los elementos tarden mucho en procesarse. En algunos casos, puede tener una operación de larga duración. También es útil si está depurando y se ha detenido en una línea mientras se está procesando; no desea que se queje antes de tener la oportunidad de investigar un problema.

Pedro
fuente
44
¡Tocar el asunto exacto! Gracias. Tuve que ir a Personalizar y agregar Excepciones al menú Depurar. No es el aspecto más intuitivo de la interfaz de usuario. Herramientas \ Personalizar, luego Reorganizar comandos (botón), luego Seleccionar depuración del menú desplegable en la esquina superior derecha, luego Agregar (botón). ¡Uf!
SeaDrive
81
ctrl-alt-etrae el cuadro de diálogo de excepción.
Florian Doyon
1
Muchas de las versiones más recientes de Visual Studio (2012, 2010, 2008) y posiblemente algunas anteriores, permiten elegir el uso principal de Visual Studio cuando se ejecuta por primera vez después de la instalación. Esa elección determina el diseño predeterminado de las barras de herramientas, incluido qué controles están visibles u ocultos, e incluso qué pulsaciones de teclas corresponden a qué comandos. En VS 2010, el Asistente de configuración de importación y exportación le permite restablecer uno de los valores predeterminados disponibles.
Zarepheth
44
@ B.ClayShannon: ContextSwitchDeadlock es específico del depurador. Una versión de lanzamiento del exe no mostrará este mensaje.
Pedro
9
En VS 2013, navegue con Debug -> Windows -> Exceptions Settings. Luego use la búsqueda
Markus Weber
16

Como dijo Pedro, tiene un problema con el depurador que impide que la bomba de mensajes se transmita por el código.

Pero si está realizando una operación de larga ejecución en el subproceso de la interfaz de usuario, llame a Application.DoEvents () que explícitamente bombea la cola de mensajes y luego devuelve el control a su método actual.

Sin embargo, si está haciendo esto, recomendaría mirar su diseño para que pueda realizar el procesamiento desde el hilo de la interfaz de usuario para que su interfaz de usuario permanezca agradable y ágil.

Spence
fuente
14

Parece que está haciendo esto en el hilo principal de la interfaz de usuario en la aplicación. El subproceso de la interfaz de usuario es responsable de bombear mensajes de Windows a medida que llegan y, sin embargo, debido a que el suyo está bloqueado en las llamadas a la base de datos, no puede hacerlo. Esto puede causar problemas con los mensajes de todo el sistema.

Debería buscar generar un subproceso en segundo plano para la operación de larga ejecución y colocar algún tipo de diálogo "Estoy ocupado" para el usuario mientras sucede.

Rob Walker
fuente
13

En Visual Studio 2017, desmarcó la opción ContextSwitchDeadlock de la siguiente manera:

Depurar> Windows> Configuración de excepciones

ingrese la descripción de la imagen aquí

En la configuración de excepción de Windows: desmarque la opción ContextSwitchDeadlock

ingrese la descripción de la imagen aquí

Hassan Rahman
fuente
9

Si no desea deshabilitar esta excepción, todo lo que necesita hacer es dejar que su aplicación envíe algunos mensajes al menos una vez cada 60 segundos. Evitará que ocurra esta excepción. Intente llamar a System.Threading.Thread.CurrentThread.Join (10) de vez en cuando. Hay otras llamadas que puede hacer que permiten que los mensajes se activen.


fuente
¿Podría explicar por qué esto ayuda?
llega el
Esto no funcionará, tengo un bucle que actualiza la interfaz de usuario y sigo recibiendo el mensaje de error.
htm11h
1
No es necesario usar un valor de 10 milisegundos, de hecho, si tiene la intención de llamarlo repetidamente en una operación de larga duración, eso disminuirá mucho el rendimiento general (tiempo total de ejecución). Simplemente pasa cero a él.
ElektroStudios
Tuve un problema similar Encontré su solución para trabajar. ¡Gracias!
Sk Shahnawaz-ul Haque
2

La solución anterior es buena en algunos escenarios, pero hay otro escenario en el que esto sucede cuando realiza pruebas unitarias e intenta "Depurar pruebas seleccionadas" desde el Explorador de pruebas cuando su solución no está configurada para Depurar.

En este caso, debe cambiar su solución de Release o lo que sea que esté configurado como Debug en este caso. Si este es el problema, cambiar "ContextSwitchDeadlock" realmente no te ayudará.

¡Me perdí esto porque el mensaje de error era tan desagradable que no comprobé lo obvio que era la configuración de depuración!

Ewan
fuente
1

En Visual Studio 2017 versión en español.

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

y busque "ContextSwitchDeadlock". Luego, desmárquelo. O atajo

Ctrl + D, E

Mejor.

kahonmlg
fuente
0

Puede resolver esto desmarcando contextswitchdeadlock de

Depurar-> Excepciones ... -> Expandir nodo MDA -> desmarcar -> contextswitchdeadlock

KR Akhil
fuente
0

Estaba recibiendo este error y cambié las consultas a async (aguarde (...). ToListAsync ()). Todo bien ahora.

Dunwan
fuente