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 ...
随机推荐
- 抓包工具-Charles
1.简介Charles Charles其实是一款代理服务器,通过成为电脑或者浏览器的代理,然后截取请求和请求结果达到分析抓包的目的.charles有Window版本和Mac OS版本,也同时支持ios ...
- 从0到1认识XHTML
XHTML概念 XHTML是一种可扩展超文本标记语言,与HTML(超文本标记语言)类似,不过在语法上更加严格.XHTML是以XML(是一种必须正确标记且格式良好的标记语言)应用方式定义的HTML,与h ...
- 团队开发day08
web端数据处理出现问题,不能通过servlet中的request获取属性值, 查找一番,前端的form设置上传数据格式为二进制类型,需要先转化,接收为 fileitem,在进行处理
- Java的代理模式
最近在学习Spring,关于Spring AOP的代理模式不是很了解,看了一篇博文就懂了. https://www.cnblogs.com/cenyu/p/6289209.html Java的三种代理 ...
- 痞子衡嵌入式:嵌入式Cortex-M裸机环境下临界区保护的三种实现
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是Cortex-M裸机环境下临界区保护的三种实现. 搞嵌入式玩过 RTOS 的朋友想必都对 OS_ENTER_CRITICAL().OS_ ...
- 微信小程序云开发-云存储的应用-识别银行卡
一.准备工作 1.创建云函数identify.自定义action=="2"的时候识别银行卡信息. 2.云函数identify中index.js代码 1 const cloud = ...
- PAT乙级:1063 计算谱半径 (20分)
PAT乙级:1063 计算谱半径 (20分) 题干 在数学中,矩阵的"谱半径"是指其特征值的模集合的上确界.换言之,对于给定的 n 个复数空间的特征值 { a1+b1i,⋯,a** ...
- Discuz! X3.4 邮件设置 使用qq邮箱发邮件
1. 在qq邮箱->设置中,获取授权码 2. 在discuz后台配置基础信息 3. 在服务器的防火墙中添加规则,允许访问465端口
- IDEA web项目小坑
1.明明依赖包都加进来了,为什么运行起来报java.lang.ClassNotFoundException? 依赖包的路径只能为{project}web/WEB-INF/lib,如果将lib改为lib ...
- 解决跨网段intouch嵌入视频问题
在自控项目中,一般会将视频网络和自控网络分开,分属于两个不同的逻辑网段,以避免局域网ip不够用的问题.这就造成了一个问题,如何实现在自控网络上位机访问摄像头并嵌入使用?这里其实很简单,因为这两个网络本 ...