使用Visual Studio,在连接到Process并按Pause(Break-All)后,切换到所需的线程并使用Quick Watch窗口检出一些数据,比如说
MySingletonClass.Instance.Data
有时候我得到这个:
无法计算表达式,因为当前线程处于休眠,等待或加入
或者(当试图查看数据的某些属性时):
坦白地说,我不在乎,我只是想看看数据!我知道有各种方法来解决这个问题,即:无法计算表达式,因为本机帧位于调用堆栈的顶部。
鉴于你可以看到这些数据,如果你大概使用了windbg为什么我们都无法利用更简单,更漂亮的VS来连接到一个进程时检查对象?
答案 0 :(得分:22)
为什么我们不能这样做?我们不能这样做,因为Visual Studio监视窗口不只是从内存中检索数据并显示它。它实际上执行托管代码(这就是“评估表达式”的含义)。特别是,它几乎总是执行ToString()
方法来显示用户可读的结果。
关键是它在您正在调试的进程/线程中执行此代码 。这可以确保表达式的计算方式与在调试代码中的实际情况相同。这样做的缺点是它只能在托管指令之间执行,但在本机代码处于活动状态时不会执行,而不是在阻塞的线程中执行。
我们可以对此做些什么?如果您实际上正在调试托管应用程序,并且您处于本机堆栈框架中,请反复按F10或Shift + F11,直到您返回托管代码。然后你可以评估表达式。但是,对于完全本机进程以及处于阻塞状态的线程,我不知道有任何解决方法。
答案 1 :(得分:4)
答案 2 :(得分:3)
只需按下Shift-F11,直到托管堆栈帧位于堆栈顶部,您就可以在VS中执行所需操作。
它基本上归结为这样一个事实,即在流程执行期间在某些点评估表达式是不安全的,否则您可能会破坏运行时。 WinDbg不保护您的运行时。 VS确实。
答案 3 :(得分:2)
问题是,这不是您想要查看的数据,而是运行某些代码的结果。在.Net属性中实际上只是伪装的方法,因此为了获取属性的值,Visual Studio需要执行应用程序代码(此功能称为FuncEval)。
此代码必须在某个线程上运行,VS所做的是它使用其中一个应用程序线程。有a number of situations,VS无法运行代码以产生结果,就在您看到正在讨论的错误消息时。
答案 4 :(得分:0)
如果您单步执行下一条指令,调试器可能有足够的时间在超时之前对其进行评估。
注意,这不会一直有效。
答案 5 :(得分:0)
如果您的项目是客户端服务器,请尝试重新上载引用MySql.Data.dll
答案 6 :(得分:0)
我知道这是一个kludge,但我对它的工作方式感到满意。在Main()方法的最后,它最初启动所有内容并创建所有其他数据结构和线程然后终止,我坚持这一点:
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);
}
而不是做一个“全部打破”我只是在大括号上贴了一个断点{。该计划中断。我有一个可用的线程,以及对所有内容的引用,因此我可以轻松浏览所有数据结构和所有线程,随处查看所有内容。