I. Memory leaks caused by events
1. No manual logoff events and no memory leaks
We often write EventHandler + = Afunction; If you do not manually unregister this event handler similar to: eventhandler–= afunction A memory leak may occur.
Public classProgram {Static voidShowmemory () {Console.WriteLine ("Shared Memory: {0}m"Gc. Gettotalmemory (true) /1024x768/1024x768); } Static voidMain (string[] args) {showmemory (); for(inti =0; I <5; i++) {eventsample es=Neweventsample (); Es. Showcomplete+=es. MyEventHandler; Gc. Collect (); Gc. WaitForPendingFinalizers (); Gc. Collect (); Showmemory (); } console.readkey (); } } Public classEventsample {byte[] M_extramemory =New byte[1024x768*1024x768* A]; //Define an event Public EventEventHandler Showcomplete; //Triggering Events Public voidOnshowcomplete () {//determines whether an event-handling method is bound, null means no event-handling method if(Showcomplete! =NULL) { //triggers an event as if it were called a methodShowcomplete ( This,NewEventArgs ()); } } //Event Handling Methods Public voidMyEventHandler (Objectsender, EventArgs e) {Console.WriteLine ("who triggered me? "+sender. ToString ()); } }
The above code output is as follows:
From the output point of view, the memory is properly recycled by GC, no problem.
2, Memory leakage situation
Let's change the code a little bit.
Public classProgram {Static voidShowmemory () {Console.WriteLine ("Shared Memory: {0}m"Gc. Gettotalmemory (true) /1024x768/1024x768); } Static voidMain (string[] args) {showmemory (); for(inti =0; I <5; i++) { Microsoft.Win32.SystemEvents.DisplaySettingsChanged + = new EventHandler (New MyMethod (). systemevents_displaysettingschanged); Gc. Collect (); Gc. WaitForPendingFinalizers (); Gc. Collect (); Showmemory (); } console.readkey (); } } Public classMyMethod {byte[] M_extramemory =New byte[1024x768*1024x768* A]; Public voidSystemevents_displaysettingschanged (Objectsender, EventArgs e) { } }
The output results are as follows:
From the output, the memory can no longer be recycled by GC. Why does this happen? Let's take a look at the source code of Microsoft.Win32.SystemEvents.DisplaySettingsChanged (omit the front and back sections):
Public Sealed class SystemEvents { ... ... Public Static Event EventHandler displaysettingschanged ... }
Why there is a difference, the fundamental difference is that the latter has a systemevents.displaysettingschanged event, and this event is static.
3. Releasing Resources
If we want to release resources, we need to implement-=afunction operations somewhere
Public classProgram {Static voidShowmemory () {Console.WriteLine ("Shared Memory: {0}m"Gc. Gettotalmemory (true) /1024x768/1024x768); } Static voidMain (string[] args) {showmemory (); for(inti =0; I <5; i++) { using (MyMethod MyMethod = new MyMethod ()) {Microsoft.Win32. SystemEvents. Displaysettingschanged+=NewEventHandler (mymethod.systemevents_displaysettingschanged); } GC. Collect (); Gc. WaitForPendingFinalizers (); Gc. Collect (); Showmemory (); } console.readkey (); } } Public class MyMethod : IDisposable {byte[] M_extramemory =New byte[1024x768*1024x768* A]; Public voidSystemevents_displaysettingschanged (Objectsender, EventArgs e) { } Public void Dispose () {Microsoft.Win32.SystemEvents.DisplaySettingsChanged-= new EventHandler (systemevents_displaysettingschanged); } }
The output is as follows:
Adding a Dispose to implement the "-=" function is OK.
Second, pay attention to static, single case
The static object has a long life cycle and is never recycled by GC, and once it is referenced by him, it is impossible to release it. The above example is a static displaysettingschanged Reference that cannot be recycled.
Another thing to note is the Singleton singleton pattern implementation class, they are also static life cycle is very long, pay attention to the reference chain, whether your class is referenced by it, if on its reference chain, the memory leaks.