zoukankan      html  css  js  c++  java
  • C#比较两个对象是否为同一个对象。 Visual Studio调试器指南---多线程应用程序调试(一)

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

    1、使用object.ReferenceEquals()

    复制代码
    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
    复制代码

    2.使用object.equals()

    复制代码
    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; }
            }
        }
      //结果同上
    复制代码

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

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

    复制代码
    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
            }
    复制代码

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

    总结:

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

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

    所以用第一种。

    线程是操作系统向其授予处理器时间的指令序列。 在操作系统中运行的每个进程都包含至少一个线程。 包含多个线程的进程称为多线程。有多个处理器、多核处理器或超线程进程的计算机可以同时运行多个线程。 使用多个线程的并行处理可以极大地提高程序性能,但也可能导致调试变得更加困难,因为正在跟踪多个线程。

    多线程处理可能会引入新类型的潜在 bug。 例如,两个或多个线程可能需要访问同一资源,但是一次只能有一个线程可以安全地访问该资源。 需要某种形式的互斥才能确保每次只有一个线程访问该资源。 如果未正确实现互斥,则可能会创建不会执行任何线程的死锁情况。 死锁通常是一个难以调试的问题。

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

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

    • 对于线程,调试线程的主要工具有 "线程" 窗口、源窗口中的线程标记、"并行堆栈" 窗口、"并行监视" 窗口和 "调试位置" 工具栏。

    • 对于使用任务并行库(TPL)或并发运行时的代码,用于调试的主要工具是 "并行堆栈" 窗口、"并行监视" 窗口和 "任务" 窗口,该窗口还支持JavaScript. 

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

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

    Visual Studio 还提供功能强大的断点和跟踪点,在调试多线程应用程序时,这会很有用。 使用断点条件和筛选器将断点置于单个线程上。 使用跟踪点可以在不中断的情况下跟踪程序的执行,从而研究死锁之类的问题。

    调试具有用户界面的多线程应用程序可能会特别困难。 可以考虑在另一台计算机上运行应用程序并使用远程调试。 

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

    使用 "线程" 窗口调试多线程应用

    多个 Visual Studio 用户界面元素可帮助调试多线程应用。 下面介绍 "代码编辑器" 窗口、"调试位置" 工具栏和 "线程" 窗口中的多线程调试功能。 

    “启动调试”

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

    2. 选择 "调试" > "开始调试",或按F5。

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

    3. 在中断模式下,通过选择 "调试" > Windows > 线程打开 "线程" 窗口。 你必须在调试会话中才能打开或查看线程和其他调试窗口。

    检查线程标记

    1. "线程" 窗口中右键单击,然后选择菜单中的 "在源中显示线程" 。

      源代码行旁边的装订线现在显示一个线程标记图标线程标记。 线程标记指示线程在此位置停止。 如果该位置有多个已停止的线程,则会显示多个线程图标。

    2. 将指针悬停在线程标记上。 显示数据提示,并显示已停止的线程或线程的名称和线程 ID 号。 线程名称可能 <No Name>

      为了帮助识别不需要的线程,您可以在 "线程" 窗口中重命名它们。 右键单击该线程,然后选择 "重命名"。

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

    标记线程和取消标记线程

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

    在源代码编辑器或 "线程" 窗口中标记和取消标记线程。 从 "调试位置" 或 "线程" 窗口工具栏中选择是仅显示标记的线程还是显示所有线程。 从任何位置进行的选择将影响所有位置。

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

    1. 通过选择 "视图" > 工具栏 > 调试位置,打开 "调试位置" 工具栏。 还可以在工具栏区域中右键单击,然后选择 "调试位置"。

    2. "调试位置" 工具栏有三个字段: "进程"、"线程" 和 "堆栈帧"。 下拉线程列表,并记下有多少线程。 在线程列表中,当前正在执行的线程由 > 符号标记。

    3. 在源代码窗口中,将鼠标悬停在滚动条中的一个线程标记图标上,并在数据提示中选择标志图标(或一个空标志图标)。 标志图标变为红色。

      您还可以右键单击线程标记图标,指向 "标志",然后从快捷菜单中选择要标记的线程。

    4. 在 "调试位置" 工具栏上,选择 "仅显示标记的线程" 图标在 "线程" 字段的右侧显示标记的线程。 除非标记一个或多个线程,否则图标为灰显。

      只有已标记的线程才会出现在工具栏的 "线程" 下拉列表中。 若要再次显示所有线程,请再次选择 "仅显示标记的线程" 图标。

      提示

      标记了某些线程后,可以将光标放在代码编辑器中,右键单击,然后选择 "将标记的线程运行到光标处"。 请确保选择所有已标记的线程将达到的代码。 将标记的线程运行到光标处将暂停选定代码行上的线程,从而可以更轻松地通过冻结和解冻线程控制执行顺序。

    5. 若要切换当前正在执行的线程的已标记或未标记状态,请选择 "仅显示标记的线程" 按钮左侧的单个标志 "切换当前线程标记状态" 工具栏按钮。 标记当前线程对于仅显示标记的线程时查找当前线程非常有用。

    6. 若要取消标记线程,请将鼠标悬停在源代码中的线程标记上,并选择红色标记图标以清除它,或右键单击线程标记,然后选择 "取消标记"。

    在 "线程" 窗口中标记和取消标记线程

    在 "线程" 窗口中,已标记的线程旁边显示红色标志图标,而未标记的线程(如果已显示)具有空图标。

    “线程”窗口

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

    还可以右键单击行,然后从快捷菜单中选择 "标记"、"取消标记" 或 "取消标记所有线程"。

    "线程" 窗口工具栏还具有 "仅显示标记的线程" 按钮,它是两个标志图标中的 righthand。 它的工作方式与 "调试位置" 工具栏上的按钮相同,其中的一个按钮控制两个位置的显示。

    其他线程窗口功能

    在 "线程" 窗口中,选择任意列的标头以按该列对线程进行排序。 再次选择以反转排序顺序。 如果显示了所有线程,则选择标志图标列会按标记或未标记的状态对线程进行排序。

    "线程" 窗口的第二列(没有标头)是当前线程列。 此列中的黄色箭头标记当前执行点。

    "位置" 列显示每个线程在源代码中出现的位置。 选择Location项旁边的展开箭头,或将鼠标悬停在该项上,以显示该线程的部分调用堆栈。

    有关线程调用堆栈的图形视图,请使用 "并行堆栈" 窗口。 若要在调试时打开窗口,请选择 "调试"> Windows > "并行堆栈"。

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

    • "在源中显示线程" 按钮。
    • 十六进制显示,将 "线程" 窗口中的线程 ID更改为十进制格式。
    • 切换到线程,这会立即将执行切换到该线程。
    • 重命名,使你可以更改线程名称。
    • 冻结和解冻命令。

    冻结和解冻线程执行

    可以冻结和解冻线程,也可以挂起和恢复线程,以控制线程执行工作的顺序。 冻结和解冻线程可帮助解决并发性问题,如死锁和争用条件。

    提示

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

    冻结和解冻线程:

    1. 在 "线程" 窗口中,右键单击任意线程,然后选择 "冻结"。 "当前线程" 列中的暂停图标指示线程已冻结。

    2. 选择 "线程" 窗口工具栏中的列,然后选择 "挂起的计数" 以显示 "挂起的计数" 列。 冻结线程的挂起计数值为1。

    3. 右键单击冻结的线程,然后选择 "解冻"。

      暂停图标消失,"挂起的计数" 值更改为0。

    切换到另一个线程

    尝试切换到另一个线程时,可能会看到应用程序处于中断模式窗口。 此窗口告诉您该线程没有当前调试器可以显示的任何代码。 例如,你可能正在调试托管代码,但线程是本机代码。 此窗口提供了解决此问题的建议。

    切换到另一个线程:

    1. 在 "线程" 窗口中,记下当前线程 ID (当前线程列中带有黄色箭头的线程)。 你需要切换回此线程以继续运行你的应用程序。

    2. 右键单击其他线程,然后从上下文菜单中选择 "切换到线程"。

    3. 观察 "线程" 窗口中的黄色箭头位置是否已更改。 原始的当前线程标记也保留为轮廓。

      查看代码源编辑器中的线程标记上的工具提示,以及 "调试位置" 工具栏上的 "线程" 下拉列表中的列表。 观察当前线程是否也已更改。

    4. 在 "调试位置" 工具栏上,从 "线程" 列表中选择一个不同的线程。 请注意,当前线程还会在其他两个位置发生更改。

    5. 在源代码编辑器中,右键单击线程标记,指向 "切换到线程",然后从列表中选择另一个线程。 观察当前线程是否在所有三个位置发生了更改。

    在源代码中,通过线程标记,只能切换到在该位置停止的线程。 使用“线程”窗口和“调试位置”工具栏可以切换到任何线程。

    你现在已经了解了调试多线程应用程序的基础知识。 您可以使用 "线程" 窗口、"调试位置" 工具栏中的 "线程" 或 "源代码编辑器" 中的 "线程" 标记来观察、标记和取消标记线程,以及冻结和解冻线程。

    为虫子生,为虫子死,为虫子奋斗一辈子
  • 相关阅读:
    vue报错 Do not use built-in or reserved HTML elements as component id:header
    vue 报错./lib/html5-entities.js this relative module was not
    vue报错/ style-loader: Adds some css to the DOM by adding a <style> tag
    vue报错 Module not found: Error: Cannot resolve 'file' or 'directory'
    vue报错 vue-cli 引入 stylus 失败
    oracle 定时任务
    Java 基础面试题
    在Java中调用带参数的存储过程
    Linux安装JDK完整步骤
    Spring中获取数据库表主键序列
  • 原文地址:https://www.cnblogs.com/bruce1992/p/15024584.html
Copyright © 2011-2022 走看看