ti-enxame.com

Depurando enquanto pausado e 'não pode avaliar expressão'

Usando o Visual Studio, depois de anexar a um processo e pressionar Pausa (Break-All), você alterna para o thread desejado e usa a janela Quick Watch para verificar alguns dados, digamos

MySingletonClass.Instance.Data

Às vezes eu ou recebo isso:

Não é possível avaliar a expressão porque o segmento atual está em suspensão, espera ou ingresso

ou isso (ao tentar visualizar certas propriedades dos dados):

Não é possível avaliar a expressão porque um quadro nativo está no topo da pilha de chamadas.

Francamente, eu não me importo, só quero ver os dados! Eu sei que existem várias maneiras de contornar isso, a saber:

  1. Definir um ponto de interrupção no encadeamento e aguardar até que seja atingido (incômodo, nem sempre possível) 
  2. Tomando um despejo do processo e carregando de volta no VS (mesmo assim eu ainda recebo o segundo erro) 
  3. windbg

Dado você poderia ver esses dados se você presumivelmente usasse windbg por que é que todos nós não podemos tirar proveito do VS muito mais fácil e mais bonito para inspecionar objetos ao anexar a um processo?

27
wal

Por que não podemos fazer isso? Não podemos fazer isso porque a janela de exibição do Visual Studio não recupera apenas dados da memória e os exibe. Na verdade, executa o código gerenciado (é o que significa "avaliar a expressão"). Em particular, quase sempre executa o método ToString() para exibir o resultado legível pelo usuário.

O ponto crucial é que ele executa este código dentro do processo/encadeamento que você está depurando . Isso garante que a expressão seja avaliada da mesma forma que se estivesse no código que você está depurando. Isso deixa a desvantagem de que ele só pode ser executado entre as instruções gerenciadas, mas não enquanto o código nativo estiver ativo e não em um encadeamento bloqueado.

O que podemos fazer sobre isso? Se você estiver realmente depurando um aplicativo gerenciado e estiver em um stackframe nativo, pressione F10 ou Shift + F11 repetidamente até voltar ao código gerenciado. Então você pode avaliar expressões. No entanto, para processos totalmente nativos e para encadeamentos em um estado bloqueado, não estou ciente de nenhuma solução alternativa.

21
Timwi

Aqui está um link para uma discussão sobre este assunto. Aparentemente, quando os argumentos de função são structs, e a memória total necessária na pilha para chamar a função excede algum número mágico, o debugger de estúdio visual vomita.

Adicional link de discussão do framework OpenTK.

4
ja72

Basta pressionar Shift-F11 até que um quadro de pilha gerenciado esteja no topo da pilha e você será capaz de fazer o que quiser no VS.

Basicamente se resume ao fato de que não é seguro avaliar expressões em determinados pontos durante a execução do processo, ou você corre o risco de corromper o tempo de execução. O WinDbg não protege o tempo de execução de você. VS faz.

3
Jonathan Rupp

O problema é que não são dados que você quer ver, é o resultado da execução de algum código. Em .Net propriedades são realmente apenas métodos disfarçados, portanto, para obter o valor de uma propriedade, o Visual Studio precisa executar o código do aplicativo (esse recurso é conhecido como FuncEval).

Este código deve ser executado em algum thread e o que o VS faz é que ele usa um dos threads do aplicativo para isso. Existe uma série de situações onde VS não pode executar o código para produzir o resultado, e é quando você viu as mensagens de erro que você está falando. 

2
Brian Rasmussen

Se você passar para a próxima instrução, o depurador poderá ter tempo suficiente para avaliá-lo antes do tempo limite.

Note, isso não vai sempre funcionar.

0
leppie

se o seu projeto é servidor cliente, tente reupload de referência MySql.Data.dll

0
zigots007

Eu sei que este é um kludge, mas estou feliz com o jeito que funciona. No final do meu método Main (), que originalmente inicia tudo e cria todas as outras estruturas de dados e threads e, em seguida, termina, eu coloco isso:

        while (true)
        {
            // This infinite while loop just gives me a convenient place for a 
            // breakpoint, so I can see everything everywhere during debugging.
            Thread.Sleep(100);
        }

Ao invés de fazer um "Break All", eu simplesmente coloco um breakpoint na chave {. O programa quebra. Eu tenho um thread disponível e uma referência a tudo, para que eu possa navegar facilmente por todas as estruturas de dados e todos os threads, ver tudo em todos os lugares.

0
Edward Ned Harvey