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 用户界面元素可帮助调试多线程应用。 下面介绍 "代码编辑器" 窗口、"调试位置" 工具栏和 "线程" 窗口中的多线程调试功能。
“启动调试”
在
代码
行上设置断点,方法是单击左侧的滚动条线,或选择线条并按F9。断点在代码行旁边的左侧滚动条中显示为红色圆圈。选择 "调试" > "开始调试",或按F5。
应用程序在调试模式下启动,并在断点处暂停。
在中断模式下,通过选择 "调试" > Windows > 线程打开 "线程" 窗口。 你必须在调试会话中才能打开或查看线程和其他调试窗口。
检查线程标记
"线程" 窗口中右键单击,然后选择菜单中的 "在源中
。
源代码行旁边的装订线现在显示一个线程标记图标
。 线程标记指示线程在此位置停止。 如果该位置有多个已停止的线程,则会显示
图标。
将指针悬停在线程标记上。 显示数据提示,并显示已停止的线程或线程的名称和线程 ID 号。 线程名称可能
<No Name>
。为了帮助识别不需要的线程,您可以在 "线程" 窗口中重命名它们。 右键单击该线程,然后选择 "重命名"。
右键单击源代码中的线程标记可查看快捷菜单上的可用选项。
标记线程和取消标记线程
您可以标记线程以跟踪您要特别注意的线程。
在源代码编辑器或 "线程" 窗口中标记和取消标记线程。 从 "调试位置" 或 "线程" 窗口工具栏中选择是仅显示标记的线程还是显示所有线程。 从任何位置进行的选择将影响所有位置。
在源代码中标记和取消标记线程
通过选择 "视图" > 工具栏 > 调试位置,打开 "调试位置" 工具栏。 还可以在工具栏区域中右键单击,然后选择 "调试位置"。
"调试位置" 工具栏有三个字段: "进程"、"线程" 和 "堆栈帧"。 下拉线程列表,并记下有多少线程。 在线程列表中,当前正在执行的线程由 > 符号标记。
在源代码窗口中,将鼠标悬停在滚动条中的一个线程标记图标上,并在数据提示中选择标志图标(或一个空标志图标)。 标志图标变为红色。
您还可以右键单击线程标记图标,指向 "标志",然后从快捷菜单中选择要标记的线程。
在 "调试位置" 工具栏上,选择 "仅显示标记的线程" 图标在 "线程" 字段的右侧
。 除非标记一个或多个线程,否则图标为灰显。
只有已标记的线程才会出现在工具栏的 "线程" 下拉列表中。 若要再次显示所有线程,请再次选择 "仅显示标记的线程" 图标。
提示
标记了某些线程后,可以将光标放在代码编辑器中,右键单击,然后选择 "将标记的线程运行到光标处"。 请确保选择所有已标记的线程将达到的代码。 将标记的线程运行到光标处将暂停选定代码行上的线程,从而可以更轻松地通过冻结和解冻线程控制执行顺序。
若要切换当前正在执行的线程的已标记或未标记状态,请选择 "仅显示标记的线程" 按钮左侧的单个标志 "切换当前线程标记状态" 工具栏按钮。 标记当前线程对于仅显示标记的线程时查找当前线程非常有用。
若要取消标记线程,请将鼠标悬停在源代码中的线程标记上,并选择红色标记图标以清除它,或右键单击线程标记,然后选择 "取消标记"。
在 "线程" 窗口中标记和取消标记线程
在 "线程" 窗口中,已标记的线程旁边显示红色标志图标,而未标记的线程(如果已显示)具有空图标。
选择标记图标,以根据其当前状态将线程状态更改为标记或未标记。
还可以右键单击行,然后从快捷菜单中选择 "标记"、"取消标记" 或 "取消标记所有线程"。
"线程" 窗口工具栏还具有 "仅显示标记的线程" 按钮,它是两个标志图标中的 righthand。 它的工作方式与 "调试位置" 工具栏上的按钮相同,其中的一个按钮控制两个位置的显示。
其他线程窗口功能
在 "线程" 窗口中,选择任意列的标头以按该列对线程进行排序。 再次选择以反转排序顺序。 如果显示了所有线程,则选择标志图标列会按标记或未标记的状态对线程进行排序。
"线程" 窗口的第二列(没有标头)是当前线程列。 此列中的黄色箭头标记当前执行点。
"位置" 列显示每个线程在源代码中出现的位置。 选择Location项旁边的展开箭头,或将鼠标悬停在该项上,以显示该线程的部分调用堆栈。
有关线程调用堆栈的图形视图,请使用 "并行堆栈" 窗口。 若要在调试时打开窗口,请选择 "调试"> Windows > "并行堆栈"。
除了标记 、取消标记和取消标记所有线程外,线程窗口项的右键单击上下文菜单还具有:
- "在源中显示线程" 按钮。
- 十六进制显示,将 "线程" 窗口中的线程 ID更改为十进制格式。
- 切换到线程,这会立即将执行切换到该线程。
- 重命名,使你可以更改线程名称。
- 冻结和解冻命令。
冻结和解冻线程执行
可以冻结和解冻线程,也可以挂起和恢复线程,以控制线程执行工作的顺序。 冻结和解冻线程可帮助解决并发性问题,如死锁和争用条件。
提示
若要在不冻结其他线程的情况下跟踪单个线程,这也是一种常见的调试方案,请参阅开始调试多线程应用程序。
冻结和解冻线程:
在 "线程" 窗口中,右键单击任意线程,然后选择 "冻结"。 "当前线程" 列中的暂停图标指示线程已冻结。
选择 "线程" 窗口工具栏中的列,然后选择 "挂起的计数" 以显示 "挂起的计数" 列。 冻结线程的挂起计数值为1。
右键单击冻结的线程,然后选择 "解冻"。
暂停图标消失,"挂起的计数" 值更改为0。
切换到另一个线程
尝试切换到另一个线程时,可能会看到应用程序处于中断模式窗口。 此窗口告诉您该线程没有当前调试器可以显示的任何代码。 例如,你可能正在调试托管代码,但线程是本机代码。 此窗口提供了解决此问题的建议。
切换到另一个线程:
在 "线程" 窗口中,记下当前线程 ID (当前线程列中带有黄色箭头的线程)。 你需要切换回此线程以继续运行你的应用程序。
右键单击其他线程,然后从上下文菜单中选择 "切换到线程"。
观察 "线程" 窗口中的黄色箭头位置是否已更改。 原始的当前线程标记也保留为轮廓。
查看代码源编辑器中的线程标记上的工具提示,以及 "调试位置" 工具栏上的 "线程" 下拉列表中的列表。 观察当前线程是否也已更改。
在 "调试位置" 工具栏上,从 "线程" 列表中选择一个不同的线程。 请注意,当前线程还会在其他两个位置发生更改。
在源代码编辑器中,右键单击线程标记,指向 "切换到线程",然后从列表中选择另一个线程。 观察当前线程是否在所有三个位置发生了更改。
在源代码中,通过线程标记,只能切换到在该位置停止的线程。 使用“线程”窗口和“调试位置”工具栏可以切换到任何线程。
你现在已经了解了调试多线程应用程序的基础知识。 您可以使用 "线程" 窗口、"调试位置" 工具栏中的 "线程" 或 "源代码编辑器" 中的 "线程" 标记来观察、标记和取消标记线程,以及冻结和解冻线程。
C#比较两个对象是否为同一个对象。 Visual Studio调试器指南---多线程应用程序调试(一)的更多相关文章
- C#比较两个对象是否为同一个对象。
两个对象是否为同一个对象:是看两个对象是否指向堆中的同一块内存. 1.使用object.ReferenceEquals() class Program { static void Main(strin ...
- 关于vector的erase删除操作的两种不同方法,在linux与visual studio的实现讨论
关于vector的erase删除操作的两种不同方法,在linux与visual studio的实现讨论 1.前言: 最近在做某一个题时,用到了vector的删除操作,利用的是erase()函数删除符合 ...
- 编写Java程序,比较两个Dog对象是否为同一个对象
返回本章节 返回作业目录 需求说明: 重写Dog类的equals(Object obj)方法. 如果equals(Object obj)中obj为Dog类型,则判断当前 对象的dogName与obj对 ...
- ext.net 这两个id不是同一个对象,小心!
今天遇到了一个很奇怪的问题,查到最后发现是下面代码原因 代码中使用store存储js对象 mcp_liststore.data.items[3].id mcp_liststore.data.get(3 ...
- java双线程调用同一个对象+锁
两个线程(Thread)调用同一个对象(使用Runnable接口的对象ThreadJob) 误区:下一个线程会从上一个线程结束的地方开始 正解:如 public domd implements Run ...
- Java中两个线程是否可以同时访问同一个对象的两个不同的synchronized方法?
不可以!!! 多个线程访问同一个类的synchronized方法时, 都是串行执行的 ! 就算有多个cpu也不例外 ! synchronized方法使用了类java的内置锁, 即锁住的是方法所属对象本 ...
- java 多线程访问同一个对象数据保护的问题
java 多线程同时访问统一个数据的时候,会引起一些错误,后面的线程会修改数据,而前面的线程还在使用修改前的内容, 使用 synchronized 关键字,保证代码块只能有一个线程来访问 public ...
- Archive将多个对象归档到同一个文件
使用archiveRootObject:toFile:方法能够将一个对象直接写入到一个文件里.但有时候可能想将多个对象写入到同一个文件里,那么就要使用NSData来进行归档对象. NSData能够为一 ...
- Java 多个引用类型变量引用同一个对象
引用类型变量在声明后必须引用对象才能使用. 一个引用变量只能唯一指向一个对象,但同一个对象可被多个引用类型变量引用. 如:MyDate today; //将变量跟配给一个保存引用的空间(栈) toda ...
随机推荐
- .Net Core微服务——服务发现:Consul(一)
先思考一些问题:它是做什么的.以及怎么使用它.带着这些问题往下走. consul是做什么的 consul用于微服务下的服务治理.服务治理是什么?它包含但不限于:服务发现.服务配置.健康检查.键值存储. ...
- 图像处理算法的仿真平台之VGA时序
一 概述 图像处理算法一般是用matla或OpenCV实现的,若是用FPGA实现,设计思路差别极大.matlab和opencv的优势:这些工具的优势在于可以方便地载入图像文件,或输出数据到图像文件, ...
- [JS]闭包和词法环境
词法环境 词法环境(lexical environment)由两个部分组成: 环境记录--一个存储所有局部变量作为其属性的对象. 对外部词法环境的引用,与外部代码相关联. 全局词法环境在脚本执行前创建 ...
- [HAOI2012]外星人 题解
人类智慧题. 首先,只有 \(\varphi(1)=\varphi(2)=1\).再考虑题目中给的提示: \[\varphi\left(\prod_{i = 1}^m p_i^{q_i}\right) ...
- 【洛谷P2028 龙兄摘苹果】动态规划
分析 第二类striling数 考虑最后一个数到底是放在之前的任意一个集合内,还是自成一个集合 \[F_{i\ j}=F_{i-1\ j-1}+j\times F_{i-1,j} \] AC代码 #i ...
- Jmeter 学习 搭建(1)
功能 1.web自动化测试 2.接口测试 3.压力测试 4.性能测试 5.通过jdbc进行数据库测试 6.java测试 优缺点 优点 1.开源,可扩展性好 2.GUI界面,小巧灵活 3.100% j ...
- HTMLTestRunner.py 文件,已修改完成
""" A TestRunner for use with the Python unit testing framework. It generates a HTML ...
- 数据库-SQL 语法
数据库-SQL 语法 二十余年如一梦,此身虽在堪惊. 简介:数据库-SQL 语法 一.基础 模式定义了数据如何存储.存储什么样的数据以及数据如何分解等信息,数据库和表都有模式. 主键的值不允许修改,也 ...
- 第九篇 -- 可以上网,连WIFI弹出网页
最近在调试WIFI模块时,程序路径没走对,导致运行了其他的函数,修改了配置文件,之后每次连接WIFI时都会弹出网页,并且明明可以上网,下面电脑符号那儿还会出现黄标,甚是心烦.上网搜索一番,终是解决了. ...
- CreateWindow() -- 创建普通的窗口
(1)函数原型 1 HWND CreateWindow( 2 LPCTSTR lpClassName, //pointer to register class name 3 LPCTSTR lpWin ...