C#:正确使用 Wea​​kReference IsAlive 属性

2024-04-06

正如所解释的here https://msdn.microsoft.com/en-us/library/system.weakreference.isalive(v=vs.110).aspx, if WeakReference's IsAlive返回 true,则不可信任。现在,我试图理解正确的方法 https://csharp.2000things.com/2012/12/13/735-dont-trust-weakreference-isalive-if-it-returns-true/使用这个:

错误:

WeakReference dogRef = new WeakReference(dog);

// Later, try to ref original Dog

if (dogRef.IsAlive)
{
    // Oops - garbage collection on original Dog could occur here
    ((Dog)dogRef.Target).Bark();
}

Correct:

WeakReference dogRef = new WeakReference(dog);

// Later, try to ref original Dog

Dog origDog = (Dog)dogRef.Target;
if (origDog != null)
{
    origDog.Bark();
}

我的问题是,从 GC 的角度来看,两者之间有什么区别吗?if(origDog != null and dogRef.Target != null?假设,我不需要调用Dog类,但只需要检查目标是否还活着。我应该始终将目标投射到类实例还是可以检查Target反对空?

我问这个问题是因为我想在对象处于活动状态时执行一些不涉及对象本身的逻辑。


我的问题是,从 GC 的角度来看, if(origDog != null 和dogRef.Target != null 之间有什么区别吗?

With origDog那么如果origDog不为空(因为当dogRef.Target被分配给它,那么它将继续不为空,直到它被重写或变得可收集。

With dogRef.Target != null那么问题不在于那个调用——它会正常工作——而是在调用它和尝试使用它之间的时间。

(顺便说一句,虽然它需要更多的输入,但通常在堆栈上创建一个临时值而不是两次命中属性通常会稍微更有效。在调用属性时值得这样做的效率并不高打字更自然,但值得注意的是,如果不想创建临时的唯一原因dogRef担心这会给应用程序带来额外的工作)。

来自评论:

如果将 Target 与 null 进行比较会获得强引用,直到范围结束

它不会,分配也不会。重要的是要认识到范围与可收集性无关。在代码中:

void SomeMethodWhichThereforeHasAScope()
{
  Dog origDog = (Dog)dogRef.Target;
  if (origDog != null)
  {
    Console.Write(dogRef.Target == null); // probably going to be false (though sometimes reads get reordered, so there's a chance that happens).
    origDog.Bark();
  }

  Console.Write(dogRef.Target == null); // could be true or false
  var sb = new StringBuilder("I'm a string that got referenced in a call to a method");
  Console.Write(sb.ToString());
  Console.Write(dogRef.Target == null); // even more likely to be true.
}

origDog在第三次测试时处于范围内Target但之后就不再使用它了。这意味着对堆栈和/或用于调用的寄存器中的对象的引用Bark可能已用于其他用途(该方法中发生的工作越多,可能性就越大),这意味着如果 GC 启动,它可能找不到引用。

“范围”是关于你在哪里can使用变量。 GC 根据您所在的位置进行工作did用它。一旦停止使用它,GC 可能会回收它引用的对象。通常我们不在乎,因为我们在使用某些东西后就不再使用它(事实上),所以我们不会注意到。有另一个经过的参考WeakReference但改变了这一点。

这就是为什么GC.KeepAlive()存在。它实际上并没有做任何事情,它只是一种不会被优化的方法,因此,如果您想要将变量保留在范围内的唯一原因是一些不寻常的 GC 东西(WeakReference属于“不寻常的 GC 东西”类别)意味着您可能想通过该变量以外的其他东西使用同一个对象,直到此后它才会被收集KeepAlive() call.

假设,我不需要调用 Dog 类的方法,而只需要检查目标是否还活着。我应该始终将目标强制转换为类实例,还是可以检查 Target 是否为空?

检查它不为空就可以了。确实使用IsAlive很好。问题在于IsAlive纯粹是因为它可能会变成false在未来的某个时刻。对于任何检查生命的方法来说都是如此。

(我唯一一次见到卢西亚诺·帕瓦罗蒂,他还活着。从那以后我就再也没有见过他。事实上,我上次见到他时他还完全活着,但这并不能阻止他现在已经死了。WeakReference.IsAlive是完全相同的)。

顺便说一句,对于单个调用,以下内容是有效且方便的:

((Dog)dogRef.Target)?.Bark();

因为?.运营商将dup参考所以它类似于:

var temp = ((Dog)dogRef.Target)
if (temp != null)
  temp.Bark();

所以很安全。

如果对象和您将要做的工作之间存在脱节,您可以使用:

var temp = dogRef.Target;
if (temp != null)
{
   DoStuffHere();
   GC.KeepAlive(temp); // temp cannot be collected until this returns.
}

正如上面所说,KeepAlive()只是一种无操作方法,不允许编译器和抖动优化掉。因此,堆栈或寄存器中必须有一个引用才能传递给它,GC 会看到它而不是收集它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C#:正确使用 Wea​​kReference IsAlive 属性 的相关文章

  • Qt/c++ 随机字符串生成[重复]

    这个问题在这里已经有答案了 我正在创建一个应用程序 需要生成多个随机字符串 几乎就像一个由一定长度的 ASCII 字符组成的唯一 ID 这些字符混合有大写 小写 数字字符 有没有 Qt 库可以实现这一点 如果没有 在纯 C 中生成多个随机字
  • C# 中 PKCS11Interop 库的线程安全使用 [已关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在使用 PKCS11Interop 在 HSM 内执行密钥管理操作 我使用的 HSM 是 Thales PCI Express 下面是
  • 我可以将 char 或 DateTime 设置为 null 吗?

    我可以将 null 设置为char数据类型 并且DateTime在 C 中 多谢你们 这是不可能的 它是一个值类型 使用 char myChar null DateTime myDate null 这相当于 Nullable
  • 为什么像 BindingList 或 ObservableCollection 这样的类不是线程安全的?

    我一次又一次发现自己必须编写 BindingList 和 ObservableCollection 的线程安全版本 因为当绑定到 UI 时 这些控件无法从多个线程更改 我想理解的是why情况就是这样 这是设计错误还是故意的 问题是设计一个线
  • 检测反射 DLL 注入

    在过去的几年中 恶意软件 以及一些渗透测试工具 如 Metasploit 的 meterpreter 负载 已经开始使用反射 DLL 注入 PDF http www harmonysecurity com files HS P005 Ref
  • asp.net core http 如果没有内容类型标头,则删除 `FromBody` 忽略

    我在 http 中使用 bodyDELETE要求 我知道目前删除主体是非标准的 但是允许的 使用时出现问题HttpClient它不允许删除请求的正文 我知道我可以使用SendAsync 但我宁愿让我的 API 更加灵活 我希望这个机构是可选
  • 模板与非模板类,跨编译器的不同行为

    我在一些应用程序中使用编译时计数器 它确实很有用 昨天我想用 gcc 编译一个程序 我之前使用的是 msvc 并且计数器的行为在模板类中发生了变化 它在模板类中不再工作 过于简化的代码 Maximum value the counter c
  • 本地时间的内存需要释放吗?

    void log time t current time 0 tm ptm localtime current stuf 只是想确定 我是否需要在方法结束时释放 tm 指针分配的内存 不 你不应该释放它 该结构是静态分配的 检查文档 htt
  • 使用 OleDbCommand / OleDbDataAdapter 读取 CSV 文件

    我不明白为什么 但是当我使用 OleDbDataAdapter 或 OleDbCommand 读取 CSV 文件时 在这两种情况下 生成的数据结构良好 它识别文件头中的列 但行数据都是空字符串 我之前已经成功进行过多次 CSV 处理 因此我
  • 如果finally 块包含await,为什么*有时*不会在ThreadAbortException 上执行?

    UPDATE 我不认为这个问题是重复的ThreadAbortException最后可以跳过吗 https stackoverflow com questions 18002668 can threadabortexception skip
  • linq where 子句和 count 导致 null 异常

    除非 p School SchoolName 结果为 null 否则下面的代码将起作用 在这种情况下 它会导致 NullReferenceException if ExistingUsers Where p gt p StudentID i
  • 从 C# 调用时无法识别 Powershell 命令

    这是这个的延续Question https stackoverflow com questions 66280000 powershell object returns null 66280138 noredirect 1 comment1
  • 在 C# .NET 中对非 ASCII 字符进行编码

    我想向我的应用程序发送的电子邮件添加自定义标头 标头名称只能包含 ASCII 字符 但对于值和用户可能会输入 UTF 8 字符 我必须对它们进行 Base64 编码 此外 我还必须将它们解码回 UTF 8 以便在 UI 中向用户显示它们 最
  • 在 C# 命令行应用程序中包含并执行 EXE

    所以我找到了一个很棒的小 EXE 命令行应用程序 我们将其称为 program exe 它输出一些我想用 C 操作的数据 我想知道是否有一种方法可以将program exe 打包 到我的Visual Studio项目文件中 这样我就可以将编
  • 调试错误:在 vc++ 项目中使用 COM 时发生 所需的运行时?

    我为我的工作创建了一个 COM 组件 我也注册了该组件 在我的系统上 我有两个虚拟机工作站 在我的第一个工作站中 它运行良好 在我的第二个工作站中 它显示一个包含消息的错误框该程序需要一段时间并以不寻常的方式关闭 请联系应用程序管理员 我认
  • 在特定线程上运行工作

    我想要一个特定的线程 任务队列并在该单独的线程中处理任务 应用程序将根据用户的使用情况创建任务并将其排队到任务队列中 然后单独的线程处理任务 即使队列为空 保持线程活动并使用它来处理排队任务也至关重要 我尝试过几种实现TaskSchedul
  • 如何释放字符串未使用的容量

    我正在程序中处理很多字符串 这些字符串数据在读入我的程序后的整个生命周期内都不会改变 但由于 C 字符串保留了容量 因此浪费了大量肯定不会被使用的空间 我尝试释放这些空间 但没有成功 以下是我尝试过的简单代码 string temp 123
  • 如何在控制台程序中获取鼠标位置?

    如何在 Windows 控制台程序中用 C 获取鼠标单击位置 点击时返回鼠标位置的变量 我想用简单的文本命令绘制一个菜单 这样当有人点击时 游戏就会注册它并知道位置 我知道如何做我需要做的一切 除了单击时获取鼠标位置 您需要使用 Conso
  • 如何通过代理将套接字连接到http服务器?

    最近 我使用 C 语言编写了一个程序 用于连接到本地运行的 HTTP 服务器 从而向该服务器发出请求 这对我来说效果很好 之后 我尝试使用相同的代码连接到网络上的另一台服务器 例如 www google com 但我无法连接并从网络中的代理
  • 在 C# 中使用自定义千位分隔符

    在显示字符串时 我尝试不使用 字符作为千位分隔符 而是使用空格 我想我需要定义一种自定义文化 但我似乎做得不对 有什么指点吗 例如 将 1000000 显示为 1 000 000 而不是 1 000 000 no String Replac

随机推荐

  • eclipse插件编程时出现“Workbench尚未创建”错误

    随着我的 eclipse 插件启动 我得到了Root exception java lang IllegalStateException Workbench has not been created yet error 而且它似乎会导致产生
  • PHP/Symfony2 表单复选框字段

    Orm My SampleBundle Entity Subject type entity id id type integer generator strategy AUTO fields motion type smallint un
  • 理解含义的算法[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我想知道是否有任何特定的算法可以遵循
  • Vue:选择下拉菜单在更改值时清除其他输入

    我有一个带有输入值的表单 当我选择带有 v model 的选项并更改下拉值时 之前字段的输入将被清除 我制作了一个简单的代码笔来演示这一点 一段时间以来 这一直是我的痛点 但现在它开始干扰客户体验 所以我想看看为什么会发生这种情况 http
  • 带通配符的 FTP 目录部分列表

    首先我问 ftp 目录列表超时 大量子目录 https stackoverflow com questions 9230485 ftp directory listing timeout huge number of subdirs 我得到
  • 在 JFrame 中组织多个 JPanel 的好方法是什么?

    我想做的是在框架内组织五个独立的 JPanel 输出应如下所示 顶部将有一个面板 顶部面板正下方的两个面板垂直分割空间 然后另外两个面板水平分割剩余空间 我无法弄清楚如何组织如上所述的面板 我认为这是因为我不知道正确的语法 因此 非常感谢任
  • 引用在嵌套结构中的生存时间不够长

    我正在创建一系列数据结构 其中包含对较低级别结构的可变引用 我一直很愉快地与A B and C下面但我尝试添加一个新层D A B C D实际上是用于协议解码的状态机的状态 但我在这里删除了所有这些 struct A fn init A gt
  • Go 模块在 VSCode 中导入问题(“无法在任何 [...] 中找到包 [...]”)

    我遇到了可能是 Gopls 语言服务器问题 在 VSCode 中使用带有 Go 扩展的 Go 模块时 我的所有外部包导入语句都被标记为不正确 这正是我到目前为止所做的 在我的 GOPATH src github com Kozie1337
  • sbt:选择运行的主类

    我的应用程序中有大约 6 个主要类 但我通常只使用其中一个 所以我想通过 sbt 自动运行它 sbt 使得可以在 build sbt 中定义两个键 Run Key val selectMainClass TaskKey Option Str
  • 无法检索访问令牌 linkedin api

    我正在申请connect with linkedin 我正在关注分步指南 https code google com p simple linkedinphp wiki QuickStart 为了验证用户身份 我寻求了帮助this http
  • 如何绘制具有不同 colspan 的四个子图?

    我尝试使用四张图像来拟合matplotlib pyplot像下面这样 plot1 plot2 plot3 plot4 我发现的大多数例子都涵盖了如下三个图 ax1 plt subplot 221 ax2 plt subplot 222 ax
  • 当我将 targetSDK 设置为 API 30 后,我的 Android 应用程序无法正常工作;我如何找出原因?

    根据Google https developer android com distribute best practices develop target sdk 从 2021 年 8 月开始 所有新的 Google Play 应用程序除了
  • Gatsby 未生成正确的静态 HTML 文件

    我正在开发一个基于盖茨比的网站 到目前为止该网站的开发进展顺利 但在构建生产时遇到了一个问题 即我们在各个页面索引文件中没有获得任何静态 html 相反 Gatsby 似乎将尝试从 javascript 注入页面 这与我们的预期相反 我看到
  • Pandas.read_excel 读取 xlsx 文件集时出现 KeyError

    我使用 Anaconda shell 进行数据分析 上传到pandas一堆excel文件 25个文件 在此文件上https www dropbox com s 16ea1cw6k63i16p Newdata zip dl 0 https w
  • 添加两个具有不同回调的谷歌地图[重复]

    这个问题在这里已经有答案了 我的页面上有两个谷歌地图容器 第一个 id map 只是一个普通的 显示地图 第二个 id map2 是一个搜索地图 用户在其中键入输入 地图将刷新到用户键入的位置 这些地图使用相同的 api 密钥 但它们的回调
  • Request.pipe() JPEG 流

    我正在开发一个作为 ZoneMinder 中间件的 Nodejs 应用程序 简而言之 我的目标是屏蔽所有 ZoneMinder api 以便客户端不知道我是否使用 ZM 一切都很好 但有一件事让我烦恼 ZM 中有一个流 api 它提供流 J
  • PyGame:文本未出现

    我正在遵循教程 我试图让我的文本出现在屏幕上 这是我的代码 但文本不会出现 from future import division import math import sys import pygame class MyGame obje
  • 如何使用 PHP 安全地将 JSON 数据写入文件

    我有用于编辑图像的 HTML 表单 所有数据都存储在 JSON 中 当我更改当前图像时 我想通过 PHP 脚本将更改保存到文本文件中 如果我返回到上一个图像 该配置将再次从该文件发送到表单 我的问题是 如何安全地写入 读取此类数据 在哪里以
  • 在 WooCommerce 主页上隐藏“缺货”产品

    我不想在主页上显示 缺货 产品 我尝试了一些 WooCommerce 挂钩和过滤器来更改产品查询 但它不起作用 我还在 woocommerce 设置区域中检查了 隐藏缺货 但产品仍然出现 我能得到线索吗 发生了什么 我尝试使用此过滤器挂钩来
  • C#:正确使用 Wea​​kReference IsAlive 属性

    正如所解释的here https msdn microsoft com en us library system weakreference isalive v vs 110 aspx if WeakReference s IsAlive返