2009-02-23 19 views
108

Ho ricevuto un messaggio di errore che non riesco a risolvere. Proviene da Visual Studio o dal debugger. Non sono sicuro se la condizione di errore finale sia in VS, nel debugger, nel mio programma o nel database.Visual Studio: ContextSwitchDeadlock

Questa è un'applicazione Windows. Non è un'app web.

Il primo messaggio di VS è una finestra popup che dice: "Nessun simbolo viene caricato per nessun frame di stack di chiamate.Il codice sorgente non può essere visualizzato." Quando si fa clic, viene visualizzato: "ContextSwitchDeadlock è stato rilevato", insieme a un messaggio lungo riprodotto di seguito.

L'errore si verifica in un loop che analizza un DataTable. Per ogni riga, utilizza un valore chiave (HIC#) dalla tabella come parametro per un SqlCommand. Il comando viene utilizzato per creare un SqlDataReader che restituisce una riga. I dati sono confrontati. Se viene rilevato un errore, una riga viene aggiunta a un secondo DataTable.

L'errore sembra essere relativo a quanto tempo impiega la procedura per l'esecuzione (vale a dire dopo 60 secondi), non quanti errori vengono rilevati. Non penso che sia un problema di memoria. Nessuna variabile è dichiarata all'interno del ciclo. Gli unici oggetti che vengono creati sono SqlDataReaders e sono in Uso delle strutture. Aggiungi System.GC.Collect() non ha avuto alcun effetto.

Il db è un sito SqlServer sullo stesso laptop.

Non ci sono aggeggi fantastici o gadget sul modulo.

Non sono a conoscenza di nulla in questo processo che è molto diverso da quello che ho fatto decine di volte prima. Ho visto l'errore prima, ma mai su una base coerente.

Qualche idea, qualcuno?

completa errore Testo: Il CLR è stato in grado di passare da contesto COM 0x1a0b88 al contesto COM 0x1a0cf8 per 60 secondi. Il thread che possiede il contesto/l'appartamento di destinazione è più probabile che effettui un'attesa senza pompaggio o che elabori un'operazione molto lunga senza pompare messaggi di Windows. Generalmente, questa situazione ha un impatto negativo sulle prestazioni e può persino portare a un'applicazione non reattiva o all'utilizzo della memoria che si accumula continuamente nel tempo. Per evitare questo problema, tutti i thread a thread singolo apartment (STA) devono utilizzare i primitivi di attesa di pompaggio (come CoWaitForMultipleHandles) e pompare regolarmente i messaggi durante le operazioni a esecuzione prolungata.

risposta

184

Il ContextSwitchDeadlock non significa necessariamente che il codice ha un problema, solo che esiste un potenziale. Se vai a Debug > Exceptions nel menu ed espandi lo Managed Debugging Assistants, troverai che ContextSwitchDeadlock è abilitato. Se disabiliti questo, VS non ti avviserà più quando gli elementi impiegano molto tempo per essere elaborati. In alcuni casi è possibile che l'operazione abbia una durata prolungata. È anche utile se esegui il debug e ti fermi su una linea mentre questa è in fase di elaborazione: non vuoi che si lamenti prima che tu abbia avuto la possibilità di indagare su un problema.

+4

destro su! Grazie. Dovevo andare su Personalizza e aggiungere eccezioni al menu Debug. Non l'aspetto più intuitivo dell'interfaccia utente. Strumenti \ Personalizza, quindi Riorganizza i comandi (pulsante), quindi seleziona Debug dall'elenco a discesa in alto a destra, quindi Aggiungi (pulsante). Meno male! – SeaDrive

+0

Sì, sembra che alcune installazioni abbiano quelle nel menu e altre no. L'ho visto anche con altre voci di menu utili, e devo ancora capire cosa li attiva o disattiva di default. – Pedro

+46

'ctrl-alt-e' porta la finestra di dialogo delle eccezioni. –

8

Sembra che lo si stia facendo sul thread principale dell'interfaccia utente dell'app. Il thread dell'interfaccia utente è responsabile del pompaggio dei messaggi di Windows in arrivo, e tuttavia poiché il tuo è bloccato nelle chiamate al database, non è in grado di farlo. Ciò può causare problemi con i messaggi di sistema.

Si dovrebbe cercare di generare un thread in background per l'operazione di lunga durata e inserire una sorta di finestra di dialogo "Sono occupato" per l'utente mentre accade.

5

Se non si desidera disabilitare questa eccezione, è sufficiente lasciare che l'applicazione esegua il pompaggio di alcuni messaggi almeno una volta ogni 60 secondi. Impedirà questa eccezione per accadere. Prova a chiamare System.Threading.Thread.CurrentThread.Join (10) una volta ogni tanto. Ci sono altre chiamate che puoi fare che fanno pompare i messaggi.

+0

Puoi spiegare perché questo aiuta? – rolls

+0

Questo non funzionerà, ho un ciclo di aggiornamento dell'interfaccia utente e continuo a ricevere il messaggio di errore. – htm11h

13

Come ha detto Pedro, si è verificato un problema con il debugger che impedisce il messaggio pump se si passa il codice.

Tuttavia, se si esegue un'operazione a esecuzione prolungata sul thread dell'interfaccia utente, chiamare Application.DoEvents() che pompa esplicitamente la coda di messaggi e quindi restituisce il controllo al metodo corrente.

Tuttavia, se lo fai, ti consiglio di guardare il tuo disegno in modo da poter eseguire l'elaborazione del thread dell'interfaccia utente in modo che l'interfaccia utente rimanga piacevole e scattante.

0

La soluzione sopra riportata è buona in alcuni scenari ma esiste un altro scenario in cui ciò accade quando si esegue il test dell'unità e si tenta di eseguire il debug di test selezionati dall'esploratore di test quando la soluzione non è impostata su debug.

In questo caso è necessario modificare la soluzione da Release o qualsiasi altra cosa è impostata su Debug in questo caso. Se questo è il problema, cambiare "ContextSwitchDeadlock" non ti sarà di grande aiuto.

Ho perso questo perché il messaggio di errore era così brutto non ho controllato la cosa ovvia che era l'impostazione di debug!

0

Nella versione spagnola di Visual Studio 2017.

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

e cercare "ContextSwitchDeadlock". Quindi, deselezionalo. O scorciatoia

Ctrl + D, E

migliore.

0

È possibile risolvere questo deselezionando contextswitchdeadlock da

Debug-> Eccezioni ... -> Espandere il nodo MDA -> deselezionare -> contextswitchdeadlock