windows 如何释放被占用的内存

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5191897/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 16:20:01  来源:igfitidea点击:

How to release the occupied memory

c#.netwindowsvb.netwinforms

提问by Lefteris Gkinis

I have a main window in my project, and numerous other child widows inside the main.
I have noticed that. When I open the main window occupies 1500K of memory, when open one child window then adds in occupied memory 6000K.
When I open the second window doing the same. When I close the two child windows the occupied memory is not released.
So What I want is to release the occupied memory when ever I close child windows.
How I can do that?
Please advice me with some code example in vb.net if it is possible.
This problem often sawing in the computers on the Local NET not in my computer (developer computer which has the SQL server on it).

我的项目中有一个主窗口,主窗口中有许多其他儿童寡妇。
我注意到。当我打开主窗口时占用1500K内存,当打开一个子窗口时则添加占用内存6000K。
当我打开第二个窗口做同样的事情。当我关闭两个子窗口时,不会释放占用的内存。
所以我想要的是在我关闭子窗口时释放占用的内存。
我怎么能做到这一点?
如果可能,请在 vb.net 中使用一些代码示例为我提供建议。
这个问题经常出现在本地 NET 上的计算机中,而不是在我的计算机(具有 SQL 服务器的开发人员计算机)中。

采纳答案by Thomas

Using as suggested by Pranay will work as it will by default call Dispose method. else explicitly you have to call this.dispose() after calling this.close() on your child forms. But be sure you are not going to use child form elements or value after close. Since dispose will finally clear everything.

按照 Pranay 的建议使用将像默认情况下调用 Dispose 方法一样工作。否则,您必须在子窗体上调用 this.close() 后明确调用 this.dispose()。但是请确保您不会在关闭后使用子表单元素或值。由于处置将最终清除一切。

MSDNexample for disposing unmanaged resource

用于处理非托管资源的MSDN示例

Imports System
Imports System.ComponentModel

' The following example demonstrates how to create
' a resource class that implements the IDisposable interface
' and the IDisposable.Dispose method.
Public Class DisposeExample

   ' A class that implements IDisposable.
   ' By implementing IDisposable, you are announcing that 
   ' instances of this type allocate scarce resources.
   Public Class MyResource
      Implements IDisposable
      ' Pointer to an external unmanaged resource.
      Private handle As IntPtr
      ' Other managed resource this class uses.
      Private component As component
      ' Track whether Dispose has been called.
      Private disposed As Boolean = False

      ' The class constructor.
      Public Sub New(ByVal handle As IntPtr)
         Me.handle = handle
      End Sub

      ' Implement IDisposable.
      ' Do not make this method virtual.
      ' A derived class should not be able to override this method.
      Public Overloads Sub Dispose() Implements IDisposable.Dispose
         Dispose(True)
         ' This object will be cleaned up by the Dispose method.
         ' Therefore, you should call GC.SupressFinalize to
         ' take this object off the finalization queue 
         ' and prevent finalization code for this object
         ' from executing a second time.
         GC.SuppressFinalize(Me)
      End Sub

      ' Dispose(bool disposing) executes in two distinct scenarios.
      ' If disposing equals true, the method has been called directly
      ' or indirectly by a user's code. Managed and unmanaged resources
      ' can be disposed.
      ' If disposing equals false, the method has been called by the 
      ' runtime from inside the finalizer and you should not reference 
      ' other objects. Only unmanaged resources can be disposed.
      Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
         ' Check to see if Dispose has already been called.
         If Not Me.disposed Then
            ' If disposing equals true, dispose all managed 
            ' and unmanaged resources.
            If disposing Then
               ' Dispose managed resources.
               component.Dispose()
            End If

            ' Call the appropriate methods to clean up 
            ' unmanaged resources here.
            ' If disposing is false, 
            ' only the following code is executed.
            CloseHandle(handle)
            handle = IntPtr.Zero

            ' Note disposing has been done.
            disposed = True

         End If
      End Sub

      ' Use interop to call the method necessary  
      ' to clean up the unmanaged resource.
      <System.Runtime.InteropServices.DllImport("Kernel32")> _
      Private Shared Function CloseHandle(ByVal handle As IntPtr) As [Boolean]
      End Function

      ' This finalizer will run only if the Dispose method 
      ' does not get called.
      ' It gives your base class the opportunity to finalize.
      ' Do not provide finalize methods in types derived from this class.
      Protected Overrides Sub Finalize()
         ' Do not re-create Dispose clean-up code here.
         ' Calling Dispose(false) is optimal in terms of
         ' readability and maintainability.
         Dispose(False)
         MyBase.Finalize()
      End Sub
   End Class

   Public Shared Sub Main()
      ' Insert code here to create
      ' and use the MyResource object.
   End Sub

End Class

(Update)[Check]

(更新检查]

If your child form has the signature. These are by default added to a form.

如果您的孩子表格有签名。这些默认情况下会添加到表单中。

'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
    MyBase.Dispose(disposing)
End Sub

回答by Cody Gray

Some of the other answers to this question contain a disappointing amount of misinformation, while others vastly over-complicate the issue. There are a lot of misconceptions surrounding garbage collection in .NET, and the theories being bandied about here are certainly not helping the problem.

这个问题的其他一些答案包含令人失望的错误信息,而其他一些则使问题过于复杂。关于 .NET 中的垃圾收集存在很多误解,这里散布的理论当然无助于解决问题。

First of all, profiling memory usage with Windows Task Manager is a huge mistake. You will get seriously invalid information, and attempting to modify your application according to this information is only going to make things worse, rather than better. If you suspect that you have performance problems (and it's very doubtful that the majority of applications actually will experience any), you need to invest in a proper memory profiler and use that instead.

首先,使用 Windows 任务管理器分析内存使用情况是一个巨大的错误。您将获得严重无效的信息,尝试根据这些信息修改您的应用程序只会让事情变得更糟,而不是更好。如果您怀疑自己有性能问题(并且很怀疑大多数应用程序实际上会遇到任何问题),您需要投资购买合适的内存分析器并使用它。

Second, the whole point of garbage collection is that you don't have to worry about this kind of thing. And not only do you not haveto worry about it, but you shouldn'tworry about it, either. You should not be doing or attempting any type of manual memory management when writing applications targeting the .NET Framework. Resist the temptation to tinker with the internal workings of the garbage collector, and plant your fingers firmly in your ears when anyone tells you to call GC.Collectmanually to force a garbage collection to occur. I suppose I shouldn't say never, but there is hardly evera reason to do this. I'm far more likely to be suspectof code that manually invokes garbage collection than anything else.

其次,垃圾收集的全部意义在于你不必担心这种事情。您不仅不必担心,而且也不应该担心。在编写面向 .NET Framework 的应用程序时,您不应执行或尝试任何类型的手动内存管理。抵制修改垃圾收集器内部工作的诱惑,当有人告诉您GC.Collect手动调用以强制进行垃圾收集时,请将手指牢牢地放在耳朵里。我想我不应该说从不,但几乎没有理由这样做。我更有可能被怀疑手动调用垃圾收集的代码比其他任何东西都要多。

Why shouldn't you manually invoke garbage collection? Well, beyond the obvious argument that it defeats the whole point of using a managed language in the first place, it's because garbage collection is an arduously slow and expensive process. You want it to run as rarelyas possible in order to maintain peak performance. Fortunately, the programmers who implemented the garbage collection algorithms are much smarter and more experienced than either you or I: they designed it to run only when necessary, and no more often than that. You won't see an advantage of running it more often, but you willsee a disadvantage. This is supposed to be completely opaque to you as the programmer.

为什么不应该手动调用垃圾收集?嗯,除了明显的论点之外,它首先打败了使用托管语言的全部意义,这是因为垃圾收集是一个极其缓慢和昂贵的过程。您希望它尽可能地运行以保持最佳性能。幸运的是,实现垃圾收集算法的程序员比你我都更聪明、更有经验:他们将它设计为仅在必要时运行,而且不会超过这个频率。你不会看到更频繁地运行它的优势,但你看到一个劣势。作为程序员,这对您来说应该是完全不透明的。

The only exception is when you're working with unmanagedobjects, which are not collected or managed by the garbage collector. You'll be able to recognize these objects because they all implement the IDisposableinterface, which provides a Disposemethod to release unmanaged resources. On objects that expose this method, you should call it as soon as you finish using the object. Or better yet, wrap the declaration and use of the object in a usingstatement, which will automaticallyhandle disposing the object, no matter what happens(even if an exception is thrown in the code where you use the object, for example).

唯一的例外是当您使用非托管对象时,这些对象不是由垃圾收集器收集或管理的。您将能够识别这些对象,因为它们都实现了IDisposable接口,该接口提供了Dispose一种释放非托管资源的方法。在公开此方法的对象上,您应该在使用完对象后立即调用它。或者更好的是,将对象的声明和使用包装在一个usingstatement 中无论发生什么,它都会自动处理对象的处置(例如,即使在使用对象的代码中抛出异常)。

Of course, you will notice that several of the standard objects in the Windows Forms library implement the IDisposablemethod. The ubiquitous Formclass, for example, provides a Disposemethod. However, that does not necessarilymean that you are responsible for disposing of these objects manually. In general, you only need to explicitly call the Disposemethod for objects that you explicitly create—easy to remember, right? The objects created automatically by the Framework are also automatically destroyed by the Framework. For example, the controls you place on a Formobject at design-time are automatically disposed when their container form is disposed. And Formobjects themselves are automatically disposed when they are closed. This is particularly relevant to the issue brought up in your question. The documentation for the Form.Closemethodtells us this:

当然,您会注意到 Windows 窗体库中的几个标准对象实现了该IDisposable方法。例如,无处不在的Form提供了一种Dispose方法。但是,这并不一定意味着您负责手动处理这些对象。一般来说,您只需要为Dispose您显式创建的对象显式调用方法——容易记住,对吧?框架自动创建的对象也会被框架自动销毁。例如,您Form在设计时放置在对象上的控件会在其容器形式被释放时自动释放。和Form对象本身在关闭时会自动处理。这与您的问题中提出的问题特别相关。该方法文档Form.Close告诉我们:

When a form is closed, all resources created within the object are closed and the form is disposed.

[ . . . ]

The two conditions when a form is not disposed on Closeis when (1) it is part of a multiple-document interface (MDI) application, and the form is not visible; and (2) you have displayed the form using ShowDialog. In these cases, you will need to call Disposemanually to mark all of the form's controls for garbage collection.

关闭表单时,对象内创建的所有资源都将关闭,并处理该表单。

[ . . . ]

未配置表单的两个条件Close是:(1) 它是多文档界面 (MDI) 应用程序的一部分,并且该表单不可见;(2) 您已使用ShowDialog. 在这些情况下,您需要Dispose手动调用以标记表单的所有控件进行垃圾回收。

Notice that, in general, you won't find yourself ever having to call Form.Disposemanually from your code. It's impossible for a user to close a MDI child form when its MDI parent is not visible, and if you happen to close the form yourself in code when its parent is invisible, you can simply insert a call to Form.Dispose. When you show a form as a modal dialog using the ShowDialogmethod, you can conveniently wrap its creation and use in a usingstatement.

请注意,一般来说,您不会发现自己必须Form.Dispose从代码中手动调用。当 MDI 父窗体不可见时,用户不可能关闭 MDI 子窗体,并且如果您碰巧在其父窗体不可见时自己在代码中关闭窗体,则只需插入对Form.Dispose. 当您使用该ShowDialog方法将表单显示为模态对话框时,您可以方便地将其创建和使用包装在一个using语句中。

Now, recall that simply calling the Disposemethod on an object only releases unmanaged resources and marks the object as available for garbage collection. It does not immediately release the memory claimed by that object.This is important, because it's exactly what your attempts at memory profiling were focused on. You know that the objects are being disposed, because you mention that the variables become unavailable to you (you say that you're "losing their values"). That's because you cannot access disposed objects. That doesn't necessarily imply, however, that the memory they claimed has been fully released. Doing so is the job of the garbage collector, which we've already established you're not supposed to monkey with. It will wait to release the memory until the application is either idle, or it desperately needs to reusethat memory. Otherwise, it will postpone collection, and that's still OK.

现在,回想一下,简单地调用Dispose对象上的方法只会释放非托管资源并将对象标记为可用于垃圾收集。它不会立即释放该对象声明的内存。这很重要,因为这正是您尝试进行内存分析的重点。您知道对象正在被处理,因为您提到变量对您不可用(您说您正在“丢失它们的值”)。那是因为您无法访问已处理的对象。然而,这并不一定意味着他们声称的内存已经完全释放。这样做是垃圾收集器的工作,我们已经确定您不应该玩弄它。它将等待释放内存,直到应用程序空闲或迫切需要重用该内存。否则,它会推迟收集,这仍然可以

回答by Nick Martyshchenko

You can use one of memory profilers available, e.g. ANTS Memory Profiler (take a look to Using ANTS Memory Profiler to track down a memory leak in a WinForms application). You can also use WinDbg but without experience it will be more complicated than specialized tool.

您可以使用可用的内存分析器之一,例如 ANTS 内存分析器(查看使用 ANTS 内存分析器来跟踪 WinForms 应用程序中的内存泄漏)。您也可以使用 WinDbg,但如果没有经验,它会比专用工具更复杂。

One of common "memory leak" reason is adding "external" event handler to form (e.g. to static or long living object), and not remove it on form destroy, so GC "thinks" you have reference to form and not collect its data.

常见的“内存泄漏”原因之一是向表单添加“外部”事件处理程序(例如添加到静态或长寿对象),而不是在表单销毁时将其删除,因此 GC“认为”您引用了表单而不收集其数据.

Why and How to avoid Event Handler memory leaks ?

为什么以及如何避免事件处理程序内存泄漏?

.NET Memory Leak Case Study: The Event Handlers That Made The Memory Baloon

.NET 内存泄漏案例研究:制造内存气球的事件处理程序

Fundamentals of Garbage Collection

垃圾收集的基础

Dispose, Finalization, and Resource Management

处置、终结和资源管理

How to identify memory leaks in the common language runtime

如何识别公共语言运行库中的内存泄漏

How to detect and avoid memory and resources leaks in .NET applications

如何检测和避免 .NET 应用程序中的内存和资源泄漏

回答by Pranay Rana

make use of using block , which atomatically release memory

使用 using block ,它自动释放内存

Using { resourcelist | resourceexpression }
    [ statements ]
End Using

回答by Oscar Mederos

That's someting you shouldn't care about.

这是你不应该关心的事情。

The .NET Framework Garbage Collectorwill do this work for you.

.NET Framework垃圾收集器将为您完成这项工作。

The .NET Framework's garbage collector manages the allocation and release of memory for your application. Each time you create a new object, the common language runtime allocates memory for the object from the managed heap. As long as address space is available in the managed heap, the runtime continues to allocate space for new objects.

.NET Framework 的垃圾收集器管理应用程序的内存分配和释放。每次创建新对象时,公共语言运行时都会从托管堆中为该对象分配内存。只要托管堆中有可用的地址空间,运行时就会继续为新对象分配空间。

Edit:

编辑

You have to make sure you're not using the resouces you wat to be free anymore. Garbage Collector's functionalities are located in the class GCunder the namespace System.

你必须确保你不再使用你想要免费的资源。垃圾收集器的功能位于GC命名空间下的类中System

In order to invoke it, you can do GC.Collect(), although I suggest you reading more about this topic and see some examples like this one

为了调用它,你可以做GC.Collect(),但我建议你阅读更多关于这个话题,看到这样一些例子这一个

回答by Thomas

I'm no expert in VB.net but as far as I know it has a garbage collector. That normally means that closing the child windows does not free memory but if you remove all references to the child windows the garbage collector might free it in the next run.

我不是 VB.net 的专家,但据我所知它有一个垃圾收集器。这通常意味着关闭子窗口不会释放内存,但是如果您删除对子窗口的所有引用,垃圾收集器可能会在下次运行时释放它。

Additionally, you normally can "ask" the garbage collector to run but it normally does "decide" by itself when to run.

此外,您通常可以“要求”垃圾收集器运行,但它通常会自行“决定”何时运行。

回答by Felice Pollano

The garbage collector will do the work for you, so you reallyshould not mind about it. You should have a more deep look inside if and only if you are using unmanaged resources ( com interop/PInvoke ).

垃圾收集器会为你做这些工作,所以你真的不应该介意它。当且仅当您使用非托管资源 (com interop/PInvoke) 时,您才应该更深入地了解内部情况。