为什么在调试主线程时工作线程不执行?

3
我创建了一个控制台测试应用程序,它创建了一个对象并在两个单独的线程上调用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);
          }
       }

请查看 - https://dev59.com/JHM_5IYBdhLWcg3w9oaG。 - KV Prajapati
sDisplayNumber和ReverseNumbers是什么样子? - AndersK
一个问题是不能确保线程的开始时间。如果你执行了 t2.Start(),但是此时 t1 可能还没有开始,因为你在那一行暂停了,所以什么也不会发生。或许如果在 t1.Start() 和 t2.Start() 之间插入一行代码来检查线程是否已经开始,然后再启动 t2,这样可能会更好一些。 - AndersK
如果在t1.Start()和t2.Start()之间放置Console.ReadKey(),则t1将被执行。 - Ganesh R.
4个回答

6

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

如果您想暂停一个线程,可以通过Debug..Threads窗口来实现,在那里可以暂停和恢复线程。


4
就我个人而言,我不认为设置断点会中断所有线程是一种限制。当我调试多线程代码时,我希望在调试会话中准确地了解每个步骤的顺序。 - Andrew Shepherd
如果我进入线程窗口->冻结主线程并按f5,那么线程t1将执行,但是我没有办法恢复主线程,因为线程窗口失去焦点(由于断点已经跳出而变为空白)。因此,我认为以上是答案。VBSStudio默认暂停所有线程;正如安德鲁所说,这对于调试目的是有好处的。 - Ganesh R.
这个限制还是挺好的,如果你突然想要中断并查看每个线程的情况。假设我想在任何一个线程上根据条件中断。现在如果其他线程继续运行,那么我怎么能在那个时候获得程序的快照视图呢?无论如何,您可以随意冻结/解冻任何线程(一旦您中断后),然后继续进行。这对于自然的调试流程非常有用。 - Munish Goyal

2

只有在上下文切换发生时,才会开始处理另一个线程。在 CPU 决定开始处理其他任务之前,它可以轻松地完成主程序中的所有工作。

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


1

如果您不断地跟踪主线程代码,最终它会切换到其中一个工作线程。

但在您的情况下,最简单的方法是在 DisplayNumber ReverseNumbers 的第一行上设置断点,如果这正是您想要调试的内容。


事实上,我正在尝试理解线程如何工作。因此,提供了一个简单的例子。 - Ganesh R.

1

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

由于 .NET 框架同步访问标准输出,因此您的线程中只有一个将在任何时间持有该给定锁定,这可能会使您产生其他线程未运行的印象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接