C#比较两个对象是否为同一个对象。 Visual Studio调试器指南---多线程应用程序调试(一)

两个对象是否为同一个对象:是看两个对象是否指向堆中的同一块内存。

1、使用object.ReferenceEquals()

C#比较两个对象是否为同一个对象。 Visual Studio调试器指南---多线程应用程序调试(一)
class Program
    {
        static void Main(string[] args)
        {
            Person p1 = new Person();
            p1.Name = "Mark";
            Person p2 = new Person();
            p2.Name = "Marl";
            Person p3 = p1;
            Console.WriteLine(object.ReferenceEquals(p1,p2));
            Console.WriteLine(object.ReferenceEquals(p1,p3));

        }
        class Person
        {
            public string Name { get; set; }
        }
    }
   //结果:false。
        true
C#比较两个对象是否为同一个对象。 Visual Studio调试器指南---多线程应用程序调试(一)

2.使用object.equals()

C#比较两个对象是否为同一个对象。 Visual Studio调试器指南---多线程应用程序调试(一)
class Program
    {
        static void Main(string[] args)
        {
            Person p1 = new Person();
            p1.Name = "Mark";
            Person p2 = new Person();
            p2.Name = "Marl";
            Person p3 = p1;
            Console.WriteLine(p1.Equals(p2));
            Console.WriteLine(p1.Equals(p3));

        }
        class Person
        {
            public string Name { get; set; }
        }
    }
  //结果同上
C#比较两个对象是否为同一个对象。 Visual Studio调试器指南---多线程应用程序调试(一)

3、使用==    得到同样的结果。

目前来看,这三个方法都能判断两个对象是否为同一个对象。但是:

C#比较两个对象是否为同一个对象。 Visual Studio调试器指南---多线程应用程序调试(一)
static void Main(string[] args)
        {
            string s1 = new string(new char[] { 'a', 'b' });
            string s2 = new string(new char[] { 'a', 'b' });
            Console.WriteLine(s1==s2);//true
            Console.WriteLine(s1.Equals(s2));//true
            Console.WriteLine(object.ReferenceEquals(s1,s2));//false
        }
C#比较两个对象是否为同一个对象。 Visual Studio调试器指南---多线程应用程序调试(一)

这两个s1,s2是两个不同的对象,因为new了两次,在堆中存在两块不同的内存。

总结:

Equals:内部是判断两个对象中的值是否一样。

==:内部还是调用的equals方法,所以应该同上。

所以用第一种。

使用多个线程的并行处理可以极大地提高程序性能,但也可能导致调试变得更加困难,因为正在跟踪多个线程。

死锁通常是一个难以调试的问题。

用于调试多线程应用的工具

Visual Studio 提供不同的工具用于调试多线程应用程序。

  • 对于调试 GPU 上的线程,主要工具是“GPU 线程”窗口。

  • 对于进程,主要工具是“附加到进程”对话框、“进程”窗口和“调试位置”工具栏。

使用跟踪点可以在不中断的情况下跟踪程序的执行,从而研究死锁之类的问题。

可以考虑在另一台计算机上运行应用程序并使用远程调试。 

参考网址:https://www.cnblogs.com/yilang/p/12487588.html

  1. 在 代码行上设置断点,方法是单击左侧的滚动条线,或选择线条并按F9。断点在代码行旁边的左侧滚动条中显示为红色圆圈。

  2. 应用程序在调试模式下启动,并在断点处暂停。

  3. C#比较两个对象是否为同一个对象。 Visual Studio调试器指南---多线程应用程序调试(一)

检查线程标记

  1. 图标。

  2. 右键单击源代码中的线程标记可查看快捷菜单上的可用选项。

标记线程和取消标记线程

您可以标记线程以跟踪您要特别注意的线程。

从任何位置进行的选择将影响所有位置。

在源代码中标记和取消标记线程

  1. 在线程列表中,当前正在执行的线程由 > 符号标记。

  2. 标志图标变为红色。

  3. 除非标记一个或多个线程,否则图标为灰显。

    提示

    将标记的线程运行到光标处将暂停选定代码行上的线程,从而可以更轻松地通过冻结和解冻线程控制执行顺序。

  4. 标记当前线程对于仅显示标记的线程时查找当前线程非常有用。

选择标记图标,以根据其当前状态将线程状态更改为标记或未标记。

其他线程窗口功能

如果显示了所有线程,则选择标志图标列会按标记或未标记的状态对线程进行排序。

此列中的黄色箭头标记当前执行点。

选择Location项旁边的展开箭头,或将鼠标悬停在该项上,以显示该线程的部分调用堆栈。

除了标记 、取消标记和取消标记所有线程外,线程窗口项的右键单击上下文菜单还具有:

  • 切换到线程,这会立即将执行切换到该线程。
  • 重命名,使你可以更改线程名称。
  • 冻结和解冻命令。

冻结和解冻线程执行

冻结和解冻线程可帮助解决并发性问题,如死锁和争用条件。

提示

若要在不冻结其他线程的情况下跟踪单个线程,这也是一种常见的调试方案,请参阅开始调试多线程应用程序。

冻结和解冻线程:

  1. 冻结线程的挂起计数值为1。

切换到另一个线程

此窗口提供了解决此问题的建议。

切换到另一个线程:

  1. 你需要切换回此线程以继续运行你的应用程序。

  2. 原始的当前线程标记也保留为轮廓。

    观察当前线程是否也已更改。

  3. 请注意,当前线程还会在其他两个位置发生更改。

  4. 观察当前线程是否在所有三个位置发生了更改。

使用“线程”窗口和“调试位置”工具栏可以切换到任何线程。

为虫子生,为虫子死,为虫子奋斗一辈子

使用多个线程的并行处理可以极大地提高程序性能,但也可能导致调试变得更加困难,因为正在跟踪多个线程。

死锁通常是一个难以调试的问题。

用于调试多线程应用的工具

Visual Studio 提供不同的工具用于调试多线程应用程序。

  • 对于调试 GPU 上的线程,主要工具是“GPU 线程”窗口。

  • 对于进程,主要工具是“附加到进程”对话框、“进程”窗口和“调试位置”工具栏。

使用跟踪点可以在不中断的情况下跟踪程序的执行,从而研究死锁之类的问题。

可以考虑在另一台计算机上运行应用程序并使用远程调试。 

参考网址:https://www.cnblogs.com/yilang/p/12487588.html

  1. 在 代码行上设置断点,方法是单击左侧的滚动条线,或选择线条并按F9。断点在代码行旁边的左侧滚动条中显示为红色圆圈。

  2. 应用程序在调试模式下启动,并在断点处暂停。

  3. C#比较两个对象是否为同一个对象。 Visual Studio调试器指南---多线程应用程序调试(一)

检查线程标记

  1. 图标。

  2. 右键单击源代码中的线程标记可查看快捷菜单上的可用选项。

标记线程和取消标记线程

您可以标记线程以跟踪您要特别注意的线程。

从任何位置进行的选择将影响所有位置。

在源代码中标记和取消标记线程

  1. 在线程列表中,当前正在执行的线程由 > 符号标记。

  2. 标志图标变为红色。

  3. 除非标记一个或多个线程,否则图标为灰显。

    提示

    将标记的线程运行到光标处将暂停选定代码行上的线程,从而可以更轻松地通过冻结和解冻线程控制执行顺序。

  4. 标记当前线程对于仅显示标记的线程时查找当前线程非常有用。

选择标记图标,以根据其当前状态将线程状态更改为标记或未标记。

其他线程窗口功能

如果显示了所有线程,则选择标志图标列会按标记或未标记的状态对线程进行排序。

此列中的黄色箭头标记当前执行点。

选择Location项旁边的展开箭头,或将鼠标悬停在该项上,以显示该线程的部分调用堆栈。

除了标记 、取消标记和取消标记所有线程外,线程窗口项的右键单击上下文菜单还具有:

  • 切换到线程,这会立即将执行切换到该线程。
  • 重命名,使你可以更改线程名称。
  • 冻结和解冻命令。

冻结和解冻线程执行

冻结和解冻线程可帮助解决并发性问题,如死锁和争用条件。

提示

若要在不冻结其他线程的情况下跟踪单个线程,这也是一种常见的调试方案,请参阅开始调试多线程应用程序。

冻结和解冻线程:

  1. 冻结线程的挂起计数值为1。

切换到另一个线程

此窗口提供了解决此问题的建议。

切换到另一个线程:

  1. 你需要切换回此线程以继续运行你的应用程序。

  2. 原始的当前线程标记也保留为轮廓。

    观察当前线程是否也已更改。

  3. 请注意,当前线程还会在其他两个位置发生更改。

  4. 观察当前线程是否在所有三个位置发生了更改。

使用“线程”窗口和“调试位置”工具栏可以切换到任何线程。