如何在Visual Studio中调试单个线程?


254

我有一些项目的解决方案。不同项目中有几个断点。我想跟踪第一个遇到这些断点的线程,并继续跟踪该单个线程,尽管其他线程进入了相同的代码块。

我知道可以通过在断点上定义一个条件来实现这一点,即线程名称= ...或线程ID = ...,但是我的情况是负载很重的ASP.NET应用程序,并且一旦附加到w3wp.exe许多线程将达到断点。我需要一些东西ThreadLocal<break-point>

可能吗?如果是这样,怎么办?


7
@Paolo:此Web应用程序是大型Web场的心脏,在测试场景中无法模仿越野车的情况。
Xaqron 2011年

对于VS 2019,也许您应该尝试以下方法:stackoverflow.com/a/61868591/8579563
Gozo

Answers:


150

冻结/解冻线程是错误的方法,因为其他线程不会执行任何代码。

最正确和可用的方法是:

  1. 在断点窗口中按Ctrl + A(选择所有断点)。
  2. 右键单击并选择“过滤器...”。
  3. 输入“ ThreadId =(当前线程ID)”。

Visual Studio 2015及更高版本中,过程类似:

  1. 在断点窗口中按Ctrl + A(选择所有断点)。
  2. 右键单击并选择“设置...”。
  3. 检查“条件”,然后在下拉列表中选择“过滤器”
  4. 输入“ ThreadId =(当前线程ID)”。

因此所有线程均被执行,但调试器仅命中当前线程。


51
这是否会阻止“ Step”调试器命令进入其他线程?那是我遇到的一个大问题。我正在逐步执行线程,突然之间,我进入了一个完全不相关的代码部分。我不再在Visual Studio中进行开发,因此无法测试。
马特·福斯

8
右键单击断点窗口中没有“过滤器”命令...,以及如何找到当前线程ID?-您要立即进入窗口并输入内容System.Threading.Thread.CurrentThread.ManagedThreadId吗?
BrainSlugs83

5
在我的VS(2015,社区版)中,无法一次修改多个断点的设置。因此,只能将过滤器一一设置。
robert4年

5
我永远都遇到这个问题,我可以保证在上一份工作中发现一种设置使Visual Studio像eclipse一样工作,您会坚持使用正在处理的线程,但是我找不到它或任何参考资料对此。我开始怀疑我是否梦想过。
斯图

7
-1,因为这仅允许断点,但不能实际调试:单步执行/单步执行不适用于调试单个线程。
Serge Rogatch

338

这是我所做的:

  1. 设置一个条件断点,我知道该断点只会击中我要寻找的线程。

  2. 一旦断点命中,并且您位于所需的线程中,则在Visual Studio的“线程”窗口中(调试时,在Debug-> Windows-> Threads中),Ctrl+ A(选择所有线程),然后Ctrl+单击您当前所在的线程。您应该选择除要调试的线程以外的所有线程。

  3. 右键单击,然后选择“冻结”。

现在,Visual Studio将仅逐步解冻。这样做似乎要慢得多,大概是因为它必须遍历所有冻结的线程,但这为我的多线程调试带来了一些理智。


1
在我有大约8个任务在不同线程中运行的情况下,这对我不起作用。我冻结了所有其他线程并“跳过”,但是IDE冻结了一段时间,然后无论如何跳到另一个线程。
Meta-Knight

3
@Diego:我不再在该项目上工作了,但是如果它将冻结除一个线程以外的所有线程,它将改变导致该错误的情况,因为线程在多虫的情况下是互补的。尽管这是一个很好的解决方案,但似乎应该将此功能嵌入到VS中。
Xaqron

3
@ Meta-Knight您应该冻结主线程之外的所有线程。如果您愿意这样做,则不会冻结IDE
Alex Zhukovskiy 2013年

15

我刚刚发布了一个Visual Studio 2010+扩展,它可以完全满足您的需求。它是免费的:)。

介绍

此Visual Studio扩展添加了两个快捷键和工具栏按钮,以使开发人员在调试多线程应用程序时可以轻松地专注于单线程。

它极大地减少了手动进入“线程”窗口以冻结/解冻所有需要遵循的线程的需求,因此有助于提高生产率。

特征

将进一步执行限制为仅当前线程。将冻结所有其他线程。快捷方式:CTRL + T + T或“雪花”按钮。切换到下一个单线程(基于ID)。将更改当前线程并冻结所有其他线程。快捷键:CTRL + T + J或“下一步”按钮。

可以在图库官方页面Github存储库中查看


您正在使用哪个版本的VS?
欧文·梅耶

我安装了扩展程序,但是没有使其正常工作(对于我当前的项目,我使用VS2010)。[顺便说一下,我认为线程处于活动状态的问题只是在创建线程时发生,这可能是标准行为,所以我删除了之前的评论]。
2013年

3
我要检查一下。您可能是地球上唯一尝试解决Microsoft最大的调试故障之一的人。
stu 2015年

,,它不会安装在vs2012上。您是否有较新的版本,或者您将共享源代码以便我自己进行构建?
stu 2015年

@stu源代码位于Codeplex上:singlethread.codeplex.com,它应可在VS 2012和VS 2013上运行,但我尚未更新它(没有人要求它,我也没有自己的需要)。如果您可以使其在VS 2012+上轻松工作并在Codeplex上进行提交,那么我也可以在Gallery上进行推送。
欧文·梅耶

13

如果像Web应用程序一样产生多个线程,则@MattFaus答案将不起作用。我所做的是以下

  • 设置一个断点以中断我想要的函数中的线程。
  • 一旦线程到达断点并暂停,我将删除断点并继续使用F8,F10和F11进行调试,以便其他线程可以运行。

艾弗特(Aftre)阅读了所有的热门文章,这个解决方法对我有用。
Swanand Pangam '17

9

一个略有不同的做法,我使用:

  1. 创建一个正常的断点并使其命中
  2. 在您的线程窗口中查找您当前正在调试的托管线程ID
  3. 在断点窗口和选择器过滤器中右键单击断点
  4. 输入ThreadId = xxx,其中xxx是2中的线程ID
  5. 现在,您可以在不停止其他线程且没有其他线程达到断点的情况下进行调试

假设您有时间在第二个线程达到断点之前执行上述操作。如果没有,并且其他线程在完成上述操作之前达到了断点,则可以在线程窗口中右键单击它们,然后选择冻结。


3
+1。“这假设您有时间...在第二个线程达到断点之前”。我将分号包裹在锁中,并在分号上放置一个断点。第一次达到断点时,我禁用了断点。由于锁定,其他线程无法进入。 lock(m_someObject) { ; }
bluedog 2015年

为了保存您的Google,“线程”窗口位于“调试”>“ Windows”>“线程”下。
加布

2

在VS 2019中:

  1. 在某处设置断点。
  2. 按下F5(继续),直到出现线程。
  3. 单击断点将其删除。
  4. 您可以使用F10或F11步进线程。

也适用于VS2015!
史前企鹅

1

我建议在实时服务器上将应用程序的另一个实例添加到同一硬件或新机器上(将其群集),然后仅调试该实例。我不会在用户触发的代码中添加断点。如果这不是一个选择,我将添加更多跟踪。

但是,如果这绝对必要并且您需要解决方案统计信息,那么我可以确定您可以添加仅在请求来自您的IP地址时才中断的断点。您可以通过添加一个条件断点来进行检查HttpContext.Request.UserHostAddress。但是请注意,这会大大降低您的应用程序的速度。


那就是我尝试过的。问题是该实例不在同一域上运行(在IP或其他域上运行),这会导致许多证书问题(SSL,WCF等),并且在低负载下也不会发生多虫问题!
Xaqron 2011年

抱歉,我不确定您尝试过其中哪一种,是否尝试过条件断点?
steinar 2011年

是的,我根据它们的托管ID对其进行命名以确保唯一性。然后,很难猜测分配了哪个ID并根据猜测设置条件。有时猜测很接近,有时要花很长时间才能抓住线索。
Xaqron 2011年

1

如果您不想停止所有其他线程(也许您将Visual Studio调试器附加到正在运行的需要响应请求的应用程序),则可以使用自动创建和删除断点的宏。

在Visual Studio中调试多线程程序时,对堆栈溢出问题“跨步”的答案中建议了这一点。

但是,该链接仅说明如何逐行调试。我建议您修改宏(如果您愿意的话),以使其修改所有断点(例如,在给定的行范围内)以仅在当前线程上停止。


1

我认为这与Visual Studio 2015稍有不同。它们在断点处进行了一些更改,但以下是如何应用hzdbyte中可接受的答案的方法(如上所述):

在编码边距的断点上,右键单击>条件>从“条件表达式”更改为“过滤器”。然后,这使您可以按ThreadId进行过滤。

或者,在“断点”窗口中的断点上,右键单击>设置>选中条件框,然后执行上述操作。


1

通过右键单击该行的侧栏来设置断点条件。选择“条件”,然后输入以下内容,并在引号中加上您的线程名称:

System.Threading.Thread.CurrentThread.Name ==“ name_of_your_thread”

或者,您可以通过从“线程”窗口获取线程的“托管ID”来执行相同操作,并使用:

System.Threading.Thread.CurrentThread.ManagedThreadId ==您的托管线程主题

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.