C#和vs2008中的线程调试

时间:2022-11-18 19:35:51

I have a pretty serious multithreaded debugging problem. I have some kind of timing issue when interacting with a serial device, and I need to track it down. I have three threads:

我有一个非常严重的多线程调试问题。在与串行设备交互时我遇到了某种时序问题,我需要跟踪它。我有三个主题:

  1. The main thread for UI updates. The user can either change one parameter of the device, or many all at once by choosing a preset.
  2. UI更新的主要线程。用户可以通过选择预设来更改设备的一个参数,或者一次更改多个参数。

  3. The status checking thread that queries to make sure that the device is still attached. If the user shuts off the device or the device itself is interacted with in an interesting way, the status changes need to be reflected in the UI.
  4. 查询以确保设备仍然连接的状态检查线程。如果用户关闭设备或设备本身以有趣的方式与之交互,则状态更改需要反映在UI中。

  5. The thread that reads the serial port where the device responds.
  6. 读取设备响应的串行端口的线程。

My problem actually has to do with debugging this situation. It seems like every single line I have in each thread has to have a breakpoint in order to be debugged; if I break in one thread, the debugger won't step through that thread. I understand that the other threads will continue to update, but shouldn't the thread I'm on execute like normal in the debugger, ie, go from one line to the next? Then, I could use the 'threads' tab to switch between threads.

我的问题实际上与调试这种情况有关。看起来我在每个线程中的每一行都必须有一个断点才能进行调试;如果我在一个线程中断,调试器将不会单步执行该线程。我知道其他线程将继续更新,但是我不应该在调试器中执行正常的线程,即从一行到下一行?然后,我可以使用'threads'选项卡在线程之间切换。

I mention that I'm in WPF because I don't know if that changes the situation at all; maybe it does, maybe it doesn't. The status checking thread is part of a UI control, because the status needs to only be checked while the UI is up. That control is in a library distinct from the main application.

我提到我在WPF,因为我不知道这是否会改变情况;也许它确实如此,也许它没有。状态检查线程是UI控件的一部分,因为只需在UI启动时检查状态。该控件位于与主应用程序不同的库中。

3 个解决方案

#1


If your code is single stepping in a weird manner, it can sometimes be caused by a simple broken pdb file. A "rebuild all" on your code will regenerate it from scratch and cure any such glitches.

如果你的代码是单一的步骤,它有时可能是由一个简单的破坏的pdb文件引起的。代码上的“全部重建”将从头开始重新生成并修复任何此类故障。

Another thing to bear in mind is that stopping one thread in the debugger can cause all kinds of unusual timing that you wouldn't see in a release build. For example:

另外要记住的是,在调试器中停止一个线程会导致您在发布版本中看不到的各种异常时序。例如:

  • the Serial port will always continue to operate (on a hardware/driver level) while you have stopped on a breakpoint - when you next try to step your code, it can receive a sudden huge burst of data. With async callbacks this can be "interesting".

    当您在断点处停止时,串行端口将始终继续运行(在硬件/驱动程序级别) - 当您下次尝试步进代码时,它可能会突然收到大量数据。使用异步回调,这可能是“有趣的”。

  • Stopping one thread disturbs the normal timeslicing so that thread to thread synchronisation can get screwed up.

    停止一个线程会干扰正常的时间点,这样线程到线程的同步就会被搞砸。

#2


When the debugger stops on a breakpoint, by default it will suspend all other threads. But when you step or continue all 3 threads are resumed. When you step through code, the debugger basically sets a temporary breakpoint on the next line and resumes all the threads. The other 2 may get a chance to run before that virtual break point is hit.

当调试器在断点上停止时,默认情况下它将挂起所有其他线程。但是当你继续步骤或继续时,所有3个线程都会恢复。当您单步执行代码时,调试器基本上会在下一行设置临时断点并恢复所有线程。其他2可能有机会在该虚拟断点被击中之前运行。

You can Freeze the other threads while debugging

您可以在调试时冻结其他线程

When you're at a breakpoint select Debug | Windows | Threads. Select the threads you aren't interested in and right-click, select Freeze. This will let you focus on the one thread you're stepping through.

当你在断点处时选择Debug | Windows |线程。选择您不感兴趣的主题并右键单击,选择“冻结”。这将让您专注于您正在逐步完成的一个主题。

#3


I'm with Jason, stepping won't show the truth anymore.

我和Jason在一起,踩着将不再显示真相。

You're really better off instrumenting each line of code with a method that also increments a counter using Interlocked.Increment and adds the counter to the output (a local file is best).

使用Interlocked.Increment增加计数器并将计数器添加到输出(本地文件最好)的方法,你最好不要使用一个方法检测每行代码。

The counter is needed because the order of actual events is not always the same as the order of writes to the file. Name the threads or use the ID value in the output, too. I use MS Excel to open the file and color all rows depending upon the thread, this way I can see the interleaving operations very clearly.

需要计数器,因为实际事件的顺序并不总是与写入文件的顺序相同。命名线程或在输出中使用ID值。我使用MS Excel打开文件并根据线程为所有行着色,这样我就可以非常清楚地看到交错操作。

I have even written a wrapper to lock {} which instruments as each lock goes on/off.

我甚至写了一个包装器来锁定{}每个锁打开/关闭的仪器。

Synchro problems are horrific to t-shoot so I advise not spending more than it would take to refactor. Sometimes its an indication that the approach you're taking is sub-optimal.

同步问题对于拍摄是可怕的,所以我建议不要花费超过重构的费用。有时它表明你所采取的方法是次优的。

Remember to use volatile where necessary with IO.

请记住在必要时使用volatile与IO。

#1


If your code is single stepping in a weird manner, it can sometimes be caused by a simple broken pdb file. A "rebuild all" on your code will regenerate it from scratch and cure any such glitches.

如果你的代码是单一的步骤,它有时可能是由一个简单的破坏的pdb文件引起的。代码上的“全部重建”将从头开始重新生成并修复任何此类故障。

Another thing to bear in mind is that stopping one thread in the debugger can cause all kinds of unusual timing that you wouldn't see in a release build. For example:

另外要记住的是,在调试器中停止一个线程会导致您在发布版本中看不到的各种异常时序。例如:

  • the Serial port will always continue to operate (on a hardware/driver level) while you have stopped on a breakpoint - when you next try to step your code, it can receive a sudden huge burst of data. With async callbacks this can be "interesting".

    当您在断点处停止时,串行端口将始终继续运行(在硬件/驱动程序级别) - 当您下次尝试步进代码时,它可能会突然收到大量数据。使用异步回调,这可能是“有趣的”。

  • Stopping one thread disturbs the normal timeslicing so that thread to thread synchronisation can get screwed up.

    停止一个线程会干扰正常的时间点,这样线程到线程的同步就会被搞砸。

#2


When the debugger stops on a breakpoint, by default it will suspend all other threads. But when you step or continue all 3 threads are resumed. When you step through code, the debugger basically sets a temporary breakpoint on the next line and resumes all the threads. The other 2 may get a chance to run before that virtual break point is hit.

当调试器在断点上停止时,默认情况下它将挂起所有其他线程。但是当你继续步骤或继续时,所有3个线程都会恢复。当您单步执行代码时,调试器基本上会在下一行设置临时断点并恢复所有线程。其他2可能有机会在该虚拟断点被击中之前运行。

You can Freeze the other threads while debugging

您可以在调试时冻结其他线程

When you're at a breakpoint select Debug | Windows | Threads. Select the threads you aren't interested in and right-click, select Freeze. This will let you focus on the one thread you're stepping through.

当你在断点处时选择Debug | Windows |线程。选择您不感兴趣的主题并右键单击,选择“冻结”。这将让您专注于您正在逐步完成的一个主题。

#3


I'm with Jason, stepping won't show the truth anymore.

我和Jason在一起,踩着将不再显示真相。

You're really better off instrumenting each line of code with a method that also increments a counter using Interlocked.Increment and adds the counter to the output (a local file is best).

使用Interlocked.Increment增加计数器并将计数器添加到输出(本地文件最好)的方法,你最好不要使用一个方法检测每行代码。

The counter is needed because the order of actual events is not always the same as the order of writes to the file. Name the threads or use the ID value in the output, too. I use MS Excel to open the file and color all rows depending upon the thread, this way I can see the interleaving operations very clearly.

需要计数器,因为实际事件的顺序并不总是与写入文件的顺序相同。命名线程或在输出中使用ID值。我使用MS Excel打开文件并根据线程为所有行着色,这样我就可以非常清楚地看到交错操作。

I have even written a wrapper to lock {} which instruments as each lock goes on/off.

我甚至写了一个包装器来锁定{}每个锁打开/关闭的仪器。

Synchro problems are horrific to t-shoot so I advise not spending more than it would take to refactor. Sometimes its an indication that the approach you're taking is sub-optimal.

同步问题对于拍摄是可怕的,所以我建议不要花费超过重构的费用。有时它表明你所采取的方法是次优的。

Remember to use volatile where necessary with IO.

请记住在必要时使用volatile与IO。