Visual Studio: ContextSwitchDeadlock

167

Estou recebendo uma mensagem de erro que não consigo resolver. É originário do Visual Studio ou do depurador. Não tenho certeza se a condição de erro final está no VS, no depurador, no meu programa ou no banco de dados.

Este é um aplicativo do Windows. Não é um aplicativo da web.

A primeira mensagem do VS é uma caixa pop-up dizendo: "Nenhum símbolo é carregado para nenhum quadro da pilha de chamadas. O código-fonte não pode ser exibido". Quando isso é clicado, recebo: " ContextSwitchDeadlock foi detectado ", juntamente com uma longa mensagem reproduzida abaixo.

O erro surge em um loop que verifica uma DataTable. Para cada linha, ele usa um valor de chave (HIC #) da tabela como parâmetro para um SqlCommand. O comando é usado para criar um SqlDataReader que retorna uma linha. Os dados são comparados. Se um erro for detectado, uma linha será adicionada a uma segunda DataTable.

O erro parece estar relacionado ao tempo de execução do procedimento (ou seja, após 60 segundos), não ao número de erros encontrados. Eu não acho que seja um problema de memória. Nenhuma variável é declarada dentro do loop. Os únicos objetos criados são os SqlDataReaders e eles estão em Usando estruturas. Adicionar System.GC.Collect () não teve efeito.

O banco de dados é um site SqlServer no mesmo laptop.

Não há aparelhos ou gadgets sofisticados no formulário.

Não conheço nada neste processo que seja muito diferente do que fiz dezenas de vezes antes. Eu já vi o erro antes, mas nunca de forma consistente.

Alguma idéia, alguém?

Texto completo do erro: O CLR não conseguiu fazer a transição do contexto COM 0x1a0b88 para o contexto COM 0x1a0cf8 por 60 segundos. O encadeamento que possui o contexto / apartamento de destino provavelmente faz uma espera sem bombeamento ou processa uma operação de execução muito longa sem bombear mensagens do Windows. Essa situação geralmente tem um impacto negativo no desempenho e pode até levar o aplicativo a não responder ou o uso da memória acumular continuamente ao longo do tempo. Para evitar esse problema, todos os encadeamentos STA (Single Threaded Apartment) devem usar primitivas de espera de bombeamento (como CoWaitForMultipleHandles) e bombear rotineiramente mensagens durante operações de execução longa.

SeaDrive
fonte

Respostas:

287

A ContextSwitchDeadlocknão significa necessariamente que seu código tem um problema, só que há um potencial. Se você for Debug > Exceptionsno menu e expandir o Managed Debugging Assistants, verá que ContextSwitchDeadlockestá ativado. Se você desabilitar isso, o VS não avisará mais quando os itens demorarem muito para serem processados. Em alguns casos, você pode ter validamente uma operação de longa duração. Também é útil se você estiver depurando e tiver parado em uma linha durante o processamento - você não deseja que ela se queixe antes de ter a chance de investigar um problema.

Pedro
fonte
4
Pode apostar! Obrigado. Eu tive que ir para personalizar e adicionar exceções ao menu Debug. Não é o aspecto mais intuitivo da interface do usuário. Ferramentas \ Personalizar, Reorganize os comandos (botão), selecione Depurar no menu suspenso no canto superior direito e, em seguida, Adicionar (botão). Ufa!
2300 SeaDrive
81
ctrl-alt-etraz o diálogo de exceção.
Florian Doyon
1
Muitas das versões mais recentes do Visual Studio (2012, 2010, 2008) e, possivelmente, algumas anteriores, permitem escolher o uso principal do Visual Studio quando ele é executado pela primeira vez após a instalação. Essa opção determina o layout padrão das barras de ferramentas, incluindo quais controles são visíveis ou ocultos e até quais teclas pressionadas correspondem a quais comandos. No VS 2010, o Assistente para Configurações de Importação e Exportação permite redefinir para um dos padrões disponíveis.
Zarepheth
4
@ B.ClayShannon - ContextSwitchDeadlock é específico para o depurador. Uma versão de lançamento do exe não exibirá esta mensagem.
Pedro
9
No VS 2013, navegue com Debug -> Windows -> Exceptions Settings. Em seguida, use a pesquisa
Markus Weber
16

Como Pedro disse, você tem um problema com o depurador que impede a bomba de mensagens se você estiver percorrendo o código.

Mas se você estiver executando uma operação de longa execução no thread da interface do usuário, chame Application.DoEvents () que explode explicitamente a fila de mensagens e, em seguida, retorna o controle ao seu método atual.

No entanto, se você estiver fazendo isso, recomendo que você analise seu design para que você possa executar o processamento fora do thread da interface do usuário para que sua interface do usuário permaneça agradável e rápida.

Spence
fonte
14

Parece que você está fazendo isso no thread principal da interface do usuário no aplicativo. O thread da interface do usuário é responsável por bombear mensagens do Windows conforme a chegada e, ainda assim, porque o seu está bloqueado nas chamadas do banco de dados, ele não pode fazê-lo. Isso pode causar problemas com mensagens em todo o sistema.

Você deve gerar um encadeamento em segundo plano para a operação de longa execução e criar algum tipo de diálogo "Estou ocupado" para o usuário enquanto isso acontece.

Rob Walker
fonte
13

No Visual Studio 2017, desmarcou a opção ContextSwitchDeadlock:

Depuração> Windows> Configurações de exceção

insira a descrição da imagem aqui

Em Exception Setting Windows: Desmarque a opção ContextSwitchDeadlock

insira a descrição da imagem aqui

Hassan Rahman
fonte
9

Se você não deseja desativar essa exceção, tudo o que você precisa fazer é permitir que seu aplicativo transmita algumas mensagens pelo menos uma vez a cada 60 segundos. Isso impedirá que essa exceção aconteça. Tente ligar para System.Threading.Thread.CurrentThread.Join (10) de vez em quando. Existem outras chamadas que você pode fazer para que as mensagens bombeiem.


fonte
Você poderia explicar por que isso ajuda?
rola
Isso não vai funcionar, eu tenho um loop atualizando a interface do usuário e ainda recebo a mensagem de erro.
Htm11h
1
Não é necessário usar um valor de 10 milissegundos, na verdade, se você pretender chamá-lo repetidamente em uma operação de longa execução, isso diminuirá muito o desempenho geral (execução do tempo total). Apenas passe zero para ele.
ElektroStudios
Eu tive um problema semelhante. A sua solução está funcionando. Obrigado!
Sk Shahnawaz-ul Haque
2

A solução acima é boa em alguns cenários, mas há outro cenário em que isso acontece quando você está testando a unidade e tenta "Depurar testes selecionados" no Explorador de Testes quando a solução não está definida como Depuração.

Nesse caso, você precisa alterar sua solução de Release ou o que estiver definido como Debug neste caso. Se esse for o problema, alterar o "ContextSwitchDeadlock" não ajudará realmente.

Eu também perdi isso porque a mensagem de erro era tão desagradável que não verifiquei a coisa óbvia que era a configuração de Depuração!

Ewan
fonte
1

Na versão em espanhol do Visual Studio 2017.

"Depurar" -> "Ventanas" -> "Configuração de exceções"

e pesquise "ContextSwitchDeadlock". Em seguida, desmarque. Ou atalho

Ctrl + D, E

Melhor.

kahonmlg
fonte
0

Você pode resolver isso desmarcando contextswitchdeadlock em

Depurar-> Exceções ... -> Expandir nó MDA -> desmarcar -> contextswitchdeadlock

KR Akhil
fonte
0

Eu estava recebendo esse erro e alternei as consultas para assíncrono (aguarde (...). ToListAsync ()). Tudo bem agora.

Dunwan
fonte