[. NET Deep breath] cleans up object references. One problem is easy to ignore. net Deep breath
As we all know, an important feature of hosting code is automatic memory management, which is the garbage collection mechanism we often call. I will not repeat these advanced theories. Interested friends can read books. I have a problem with this: I don't like to talk about some theoretical things very seriously, so I don't want to talk about it much.
Generally, when code execution exceeds the valid range of a variable, or an object instance is no longer referenced, the instance will generate an analysis structure, and the Garbage Collector may need to clear the portal, of course, it may not be cleared immediately. It may be cleared later.
For some classes to be customized for cleanup, we will adopt the following solutions:
1. Write the Destructor and clear it in the destructor.
2. Implement the IDisposable interface, implement the Dispose method, and write custom cleaning code in the method. After the type is instantiated, the Dispose method will be called for cleanup when it is no longer used. If it is cleared, the type destructor will be called. Generally, you do not need to write the destructor to implement the IDisposable interface. If you want the Dispose method to be automatically called, you can wrap the code of the instantiated object in the using statement block. When the using block is executed, the Dispose method is automatically called.
Some people may have laughed. You are so funny, old Zhou. who do not know the basic knowledge? Of course, I said that the above content is for a small circle to enter the topic. Therefore, I have a question: is there some situations that may cause the object instance not to be recycled? Even if you call the Dispose method, even if you set the variable to null to release the reference, even if you call the GC class method to recycle ......
This is the case after the old week test, and many friends may ignore it. Even in terms of consciousness and cognition, the object instance has been recycled, but in fact it has not been recycled.
Let me briefly describe this situation:
For example, there is A static class (the members of the static class must be static) A, which contains static events. Then, the static events of Class A will be processed in other class instances, and the method for processing the events will be located on the instance object ......
Don't worry. Let's look at the real example. Assume that I have defined a static class MyChecker, which contains a static event CheckEvent.
Public static class MyChecker {# region static event public static event EventHandler CheckEvent; # endregion public static void CallEvent () {if (CheckEvent! = Null) {CheckEvent (new object (), EventArgs. Empty );}}}
As long as the CallEvent method is called, The CheckEvent event is triggered.
Next, define another class SampleClass and process static events in MyChecker.
Class SampleClass: IDisposable {public SampleClass () {MyChecker. CheckEvent + = MyChecker_CheckEvent;} void MyChecker_CheckEvent (object sender, EventArgs e) {new Form2 (). Show ();}~ SampleClass () {System. Diagnostics. Debug. WriteLine ("\ n, the Destructor is called. \ N ");} public void Dispose (){//...... }}
In the constructor of the class, append the CheckEvent event processing method named MyChecker_CheckEvent.
You may have discovered that the SampleClass class written by Lao Zhou is a little scary. It implements both the Dispose method and how to write the destructor, I will write the Destructor here to verify whether the instance of the class is actually cleaned up. If the instance is actually recycled, the Debug class will output a prompt in the "output" window, if no output is displayed, the instance of the class occupies the memory.
Next, let's test it.
SampleClass sc = new SampleClass(); await Task.Delay(10 * 1000); sc.Dispose(); sc = null; GC.Collect();
After the SampleClass is instantiated, Delay will pause for 10 seconds. After 10 seconds, the Dispose method will be called and the variable will be set to null reference. I am afraid that it will not be cleaned up in time to connect to GC. the Collect method is also used.
During these 10 seconds, you can call the CallEvent method of the static class to trigger the static event CheckEvent.
MyChecker.CallEvent();
In general, the SampleClass instance should be cleaned up in 10 seconds, and a prompt will be output in the "output" window.
Okay. Try it now.
......
The experimental results show that no duck hair is output in the output window, which means that the SampleClass instance has no structure after 10 seconds. So there is another problem. What is the problem? Isn't the SampleClass instance referenced? Why don't we generate a structure?
In fact, we ignore the following:The static event CheckEvent is also bound to the SampleClass instance method. In fact, although the variable is set to null, The MyChecker_CheckEvent method in the SampleClass instance is also referenced by static events in the static class., So it will not be recycled. I don't know if you understand it.
This problem is ignored by many friends in actual development. I am proud to think that the Sample instance has been recycled. In fact, the instance will not be recycled unless the program ends. Because MyChecker is a static class, it is not based on instances. If MyChecker is not a static class, the SampleClass instance can be released after the MyChecker instance is released.
So how can we solve it? It is very simple. You only need to unbind static events from methods in the Dispose method of the SampleClass class. In this way, static events no longer reference method members in the instance, now the instance can be generated.
public void Dispose() { MyChecker.CheckEvent -= MyChecker_CheckEvent; }
This example tells us:Be careful when handling static events in a class instance.
Download the source code for this example: http://files.cnblogs.com/files/tcjiaan/refsample.zip
Now, let's get to it today.