【问题标题】:Why does a worker thread not execute when debugging the main thread?为什么调试主线程时工作线程不执行?
【发布时间】:2009-08-03 16:00:54
【问题描述】:

我创建了一个控制台测试应用程序,它创建一个对象并在 2 个单独的线程上调用 2 个函数。 一个线程以相反的顺序打印从 1 到 20 的数字。

问题是在调试第一个工作线程时直到我不停止调试主线程(即我按 f5)才被触发。有答案吗?

class Program
 {
  static void Main(string[] args)
   {
     DisplayData dd = new DisplayData();

     ThreadStart ts1 = new ThreadStart(dd.DisplayNumber);
     Thread t1 = new Thread(ts1);
     t1.Name = "Display Numbers";

     ThreadStart ts2 = new ThreadStart(dd.ReverseNumbers);
     Thread t2 = new Thread(ts2);
     t2.Name = "Reverse Numbers";

     t1.Start(); //Keep 1st break point at this location. Then press F10.
     t2.Start(); //Keep break point at this location permanently
    }




public class DisplayData
   {
       public void DisplayNumber()
       {
          int length = 20;
          Console.WriteLine("\nNumbers in correct order.\n");


          for (int i = 0; i < length; i++)
          {

             Console.WriteLine("DN: The value of i is: " + (i+1) + " " + Thread.CurrentThread.ManagedThreadId + " " + Thread.CurrentThread.Name);
             //Thread.Sleep(1000);

          }
       }

       public void ReverseNumbers()
       {
          int length = 20;
          Console.WriteLine("\nNumbers in reverse order.\n");
          for (int i = 0; i < length; i++)
          {

             Console.WriteLine("RN: The value of i is: " + (length - i) + " " + Thread.CurrentThread.ManagedThreadId + " " + Thread.CurrentThread.Name);
             //Thread.Sleep(1000);
          }
       }

【问题讨论】:

  • sDisplayNumber 和 ReverseNumbers 长什么样子?
  • 一个问题是不能保证线程何时开始,如果你降级到 t2.Start(),那么 t1 可能还没有开始,但是因为你在那条线上暂停什么会发生。也许如果你在 t1.Start() 和 t2.Start() 之间放置一条线来检查线程是否启动,然后启动 t2 会更好。
  • 如果在 t1.Start() 和 t2.Start(0 之间放置 Console.ReadKey() 则 t1 执行。

标签: c# multithreading


【解决方案1】:

我不确定这是否是 Visual Studio 或 CLR 的限制,但在一个线程上设置断点会停止所有线程。

如果您想暂停线程,您可以通过 Debug..Threads 窗口执行此操作,您可以在那里暂停和恢复线程。

【讨论】:

  • 就个人而言,我不认为设置断点会中断所有线程是一种限制。当我调试多线程代码时,我想确切地知道调试会话中的步骤顺序。
  • 如果我转到线程窗口 -> 冻结主线程并按 f5,然后线程 t1 执行,但由于线程窗口失焦,我无法恢复主线程(自断点被踩出)。因此,我认为以上就是答案。 VBSStudio 默认暂停所有线程;正如 Andrew 所说,这对调试很有好处。
  • 我猜这个限制是好的,如果你突然想打破并查看每个线程的情况。假设我想打破任何线程的条件。现在如果其他线程继续运行,那么我如何获得当时程序的快照视图。无论如何,您可以随意冻结/解冻任何线程(一旦中断),然后继续。它有利于自然调试流程。
【解决方案2】:

在上下文切换发生之前,不会开始处理另一个威胁。在 CPU 决定开始其他工作之前,它可以轻松完成主例程中的所有工作。

使用t1.Join() 等待工作线程完成后再继续。

【讨论】:

    【解决方案3】:

    您会发现,如果您继续单步执行主线程代码,它最终会切换到您的工作线程之一。

    但在您的情况下,最简单的做法是在 DisplayNumberReverseNumbers 的第一行放置一个断点,如果这是您特别想要调试的。

    【讨论】:

    • 问题是我试图了解线程是如何工作的。因此是一个简单的例子。
    【解决方案4】:

    它确实“执行”了,但它不一定得到任何时间片。当您单步执行代码时,所有线程都会有效地“执行”。但是,实际运行的线程数取决于可用的 CPU。因此,根据情况,您的其他线程可能会运行也可能不会运行。

    由于 .NET 框架会同步对标准输出的访问,因此在任何时候只有一个线程会持有给定的锁,这可能会给您一种其他线程没有运行的印象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-19
      • 1970-01-01
      • 2017-06-19
      • 1970-01-01
      相关资源
      最近更新 更多