垃圾收集和终结 [英] Garbage collection and Finalization

查看:66
本文介绍了垃圾收集和终结的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好。



昨天我公司部门的一名初级开发人员为我提供了代码,并问我一个问题。

我知道代码片段有很多违规行为,我已经将它们指向了大三学生:



  • Dispose模式的不正确实现
  • 在.NET终结器中使用托管对象,等等。
  • public class FileHandler
    	{
    		private StreamReader sr;
    		private string _fname;
     
    		public FileHandler(string filename)
    		{
    			sr = new StreamReader(filename);
    		}
     
    		public void PerformRead()
    		{
    			string line = null;
    			while ((line = sr.ReadLine()) != null)
    			{
    				if (line.Contains("declare"))
    					line = line.Trim();
    			}
    		}
     
    		public void Close()
    		{
    			sr.Close();
    		}
    	}
     
    	public sealed class FileReader
    	{
    		private FileHandler fileHandler;
     
    		public FileReader(string fileName)
    		{
    			fileHandler = new FileHandler(fileName);
    		}
     
    		public void Read()
    		{
    			FileTools.ReadFile(fileHandler);
    		}
     
    		~FileReader()
    		{
    			Console.WriteLine("Closing vie finalization");
    			fileHandler.Close();
    		}
     
    		public void Dispose()
    		{
    			fileHandler.Close();
    			GC.SuppressFinalize(this);
    		}
    	}
     
    	public static class FileTools
    	{
    		public static void ReadFile(FileHandler fileHandler)
    		{
    			if (fileHandler != null)
    				fileHandler.PerformRead();
    		}
    	}
    	
    	class Program
    	{
    		static void Main(string[] args)
    		{
    			FileReader fr = new FileReader("myfile.txt");
    			fr.Read();
    		}
    	}



    注意:问题仅在发布模式下重现(当我们运行独立应用程序时,不在VS下) * .exe)这里的下一个关键障碍是我们正在处理的文件必须超过3 Mb。

    我的问题是:

    为什么在完成PerformRead方法之前,FileReader被垃圾收集(达到最终化,移动到Freachable队列并在那里倾斜)?

    因此,当处理大文件时,我们在PerformRead之前收到NullReferenceException已完成。

    在VS下我们无法观察到上述行为。

    请参阅例外链接错误打印屏幕 [ ^ ]

    推荐答案

    所以在 @manchanx

    的帮助下,我们达到了下一步:

    1)m已经发布FileReader对象并将其置于最终阶段的罪魁祸首是在Release期间打开优化并且不发出调试符号。

    这就是为什么在PerformRead方法的活动工作流中和乍一看保留所有引用活动,GC处理FileReader fr对象作为垃圾

    并将其提交到完成阶段。



    所以消除这样的问题有3个步骤:

    1)将[MethodImplAttribute(MethodImplOptions.NoInlining)]应用于Main和Read方法。

    2)尽可能多地操作fr引用尽可能:例如添加下一行:

    So with help of @manchanx
    we reached next steps:
    1) The main culprit who has been released FileReader object and put it to the finalization stage was optimization that is turned on during Release and debug symbols are not emitted.
    That is why during the active workflow in the PerformRead method and at first glance preserving all references alive , the GC treated FileReader fr object as a garbage
    and submit it to the finalization stage.

    So to eliminate such issue there are 3 steps:
    1) Apply [MethodImplAttribute(MethodImplOptions.NoInlining)] to both Main and Read methods.
    2) Operate fr reference as much as possible: for example add next lines:
    class Program
    	{
    		static void Main(string[] args)
    		{
    			FileReader fr = new FileReader("myfile.txt");
    			fr.Read();
                            Console.WriteLine(fr.GetType());
    		}
    	}





    3)添加下一个设置文件[assemblyname] .ini

    使用这些设置,您的应用程序可以全速运行。当您想通过打开调试跟踪并可能关闭(CIL)代码优化来调试应用程序时,只需使用以下设置:

    下一个文件的内容:



    [.NET Framework调试控制]

    GenerateTrackingInfo = 1

    AllowOptimize = 0



    3) Add next setting file [assemblyname].ini
    With these settings, your app runs at full speed. When you want to debug your app by turning on debug tracking and possibly turning off (CIL) code optimization, just use the following settings:
    The content of a file is next:

    [.NET Framework Debugging Control]
    GenerateTrackingInfo=1
    AllowOptimize=0


    这篇关于垃圾收集和终结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆