简体   繁体   English

C#和vs2008中的线程调试

[英]Threaded debugging in C# and vs2008

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. UI更新的主要线程。 The user can either change one parameter of the device, or many all at once by choosing a preset. 用户可以通过选择预设来更改设备的一个参数,或者一次更改多个参数。
  2. 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. 如果用户关闭设备或设备本身以有趣的方式与之交互,则状态更改需要反映在UI中。
  3. The thread that reads the serial port where the device responds. 读取设备响应的串行端口的线程。

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; 我提到我在WPF,因为我不知道这是否会改变情况; 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. 状态检查线程是UI控件的一部分,因为只需在UI启动时检查状态。 That control is in a library distinct from the main application. 该控件位于与主应用程序不同的库中。

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. 但是当你继续步骤或继续时,所有3个线程都会恢复。 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. 其他2可能有机会在该虚拟断点被击中之前运行。

You can Freeze the other threads while debugging 您可以在调试时冻结其他线程

When you're at a breakpoint select Debug | 当你在断点处时选择Debug | Windows | 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. 这将让您专注于您正在逐步完成的一个主题。

If your code is single stepping in a weird manner, it can sometimes be caused by a simple broken pdb file. 如果你的代码是单一的诡计,它有时可能是由一个简单的破坏的pdb文件引起的。 A "rebuild all" on your code will regenerate it from scratch and cure any such glitches. 代码上的“全部重建”将从头开始重新生成并修复任何此类故障。

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. 停止一个线程会干扰正常的时间点,这样线程到线程的同步就会被搞砸。

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. 命名线程或在输出中使用ID值。 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. 我使用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。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM