草庐IT

c# - .NET 4.5 Async/Await 和垃圾收集器

coder 2023-07-13 原文

我想知道 async/await 与垃圾收集局部变量相关的行为。在下面的示例中,我分配了相当大的内存部分并进入了显着的延迟。从代码中可以看出,在 await 之后没有使用 Buffer。它会在等待时被垃圾收集,还是会在函数执行期间占用内存?

/// <summary>
/// How does async/await behave in relation to managed memory?
/// </summary>
public async Task<bool> AllocateMemoryAndWaitForAWhile() {
    // Allocate a sizable amount of memory.
    var Buffer = new byte[32 * 1024 * 1024];
    // Show the length of the buffer (to avoid optimization removal).
    System.Console.WriteLine(Buffer.Length);
    // Await one minute for no apparent reason.
    await Task.Delay(60000);
    // Did 'Buffer' get freed by the garabage collector while waiting?
    return true;
}

最佳答案

Will it get garbage collected while waiting?

也许吧。允许垃圾收集器这样做,但不是必须这样做。

Will the memory be occupied for the duration of the function?

也许吧。允许垃圾收集器这样做,但不是必须这样做。

基本上,如果垃圾收集器知道缓冲区将永远不会被再次触及,那么它可以随时释放它。但是 GC 永远需要按任何特定的时间表释放任何东西。

如果您特别担心,您始终可以将本地设置为 null,但除非您确实遇到了问题,否则我不会费心这样做。或者,您可以将操作缓冲区的代码提取到它自己的非异步方法中,并从异步方法中同步调用它;然后本地就变成普通方法的普通本地。

The await is realized as a return, so the local will go out of scope and its lifetime will be over; the array will then be collected on the next collection, which is required to be during the Delay, right?

不,这些说法都不是真的。

首先,如果任务未完成,await 只是一个return;现在,当然 Delay 几乎不可能完成,所以是的,这会返回,但我们不能一般地断定 await 返回给调用者。

其次,仅当 C# 编译器在 IL 中将其实际实现为临时池中的本地时,本地才会消失。抖动会将其作为堆栈槽或寄存器进行抖动,当方法的激活在 await 结束时,它会消失。但是 C# 编译器不需要这样做!

对于调试器中的人来说,在 Delay 之后放置一个断点并看到本地已经消失,这似乎很奇怪,因此编译器可能将本地实现为编译器生成的类中的一个字段,它绑定(bind)到为状态机生成的类的生命周期。在那种情况下,抖动不太可能意识到这个字段再也不会被读取,因此也不太可能提前丢弃它。 (尽管允许这样做。而且 C# 编译器允许代表您将字段设置为 null,前提是它可以证明您已完成使用. 同样,这对于调试器中的人来说很奇怪,他们突然看到他们的本地更改值没有明显的原因,但允许编译器生成单线程行为正确的任何代码。)

第三,不需要垃圾收集器按照任何特定的时间表收集任何东西。这个大数组会分配到大对象堆上,那个东西有自己的回收时间表。

第四,没有任何东西要求在任何给定的六十秒间隔内存在大型对象堆的集合。如果没有内存压力,那东西永远不需要收集。

关于c# - .NET 4.5 Async/Await 和垃圾收集器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16598409/

有关c# - .NET 4.5 Async/Await 和垃圾收集器的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  3. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  4. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  5. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  6. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  7. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  8. .net - .NET 将如何影响 Python 和 Ruby 应用程序? - 2

    我很好奇.NET将如何影响Python和Ruby应用程序。用IronPython/IronRuby编写的应用程序是否会非常特定于.NET环境,以至于它们实际上将变得特定于平台?如果他们不使用任何.NET功能,那么IronPython/IronRuby相对于非.NET同类产品的优势是什么? 最佳答案 我不能说任何关于IronRuby的东西,但是大多数Python实现(如IronPython、Jython和PyPy)都试图尽可能忠实于CPython实现。不过,IronPython正在迅速成为这方面的佼佼者之一,并且在PlanetPyth

  9. ruby - 如何使用 Ruby HTTP::Net 处理 404 错误? - 2

    我正在尝试解析网页,但有时会收到404错误。这是我用来获取网页的代码:result=Net::HTTP::getURI.parse(URI.escape(url))如何测试result是否为404错误代码? 最佳答案 像这样重写你的代码:uri=URI.parse(url)result=Net::HTTP.start(uri.host,uri.port){|http|http.get(uri.path)}putsresult.codeputsresult.body这将打印状态码和正文。

  10. .net - 是否有 Ruby .NET 编译器? - 2

    是否有适用于Ruby语言的.NETFramework编译器?我听说过DLR(动态语言运行时),这是否将使Ruby能够用于.NET开发? 最佳答案 IronRuby是Microsoft支持的项目,建立在动态语言运行时之上。 关于.net-是否有Ruby.NET编译器?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/199638/

随机推荐