Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#单例日志类,用于在销毁时将消息存储在磁盘上_C#_Asp.net_Session_Singleton - Fatal编程技术网

C#单例日志类,用于在销毁时将消息存储在磁盘上

C#单例日志类,用于在销毁时将消息存储在磁盘上,c#,asp.net,session,singleton,C#,Asp.net,Session,Singleton,我有一个ASP.NET C#singleton(通过HttpContext.Current.session限定到一个会话),它接收来自代码(警告、错误、异常等)的消息。这些消息与代码问题有关,主要在调试时使用,而不是在生产过程中使用 我为此对象编写了自定义析构函数,以便将其内容作为文件写入/附加到磁盘上 我想问两件与这种情况有关的事情: a] 在对象析构函数期间打开并写入文件是个好主意吗?并发IO访问通过静态锁处理 b] 何时为会话作用域对象调用析构函数?是否仅当服务器上的会话过期时才使用 实现

我有一个ASP.NET C#singleton(通过HttpContext.Current.session限定到一个会话),它接收来自代码(警告、错误、异常等)的消息。这些消息与代码问题有关,主要在调试时使用,而不是在生产过程中使用

我为此对象编写了自定义析构函数,以便将其内容作为文件写入/附加到磁盘上

我想问两件与这种情况有关的事情:

a] 在对象析构函数期间打开并写入文件是个好主意吗?并发IO访问通过静态锁处理


b] 何时为会话作用域对象调用析构函数?是否仅当服务器上的会话过期时才使用

实现此功能,然后将记录器实例包装到一个块中,这将保证在记录器上调用dispose方法。

我还建议使用一些现有的日志记录包。如果你决定自己做这件事,并且只是为了将来牢记:

a) 不,这不是个好主意。您不应该访问终结器(析构函数)中的托管资源,因此,例如,如果内存中有一些日志字符串,那么访问它们(或它们所包含的列表)是不好的做法,因为此时它们可能已经被终结

我不想重复推荐的模式,所以请参见

您将看到,在
Dispose
期间,只有一个地方应该访问managed,这就是如果它是由用户代码调用的,而不是GC。因此,这应该有助于您得出这样的结论:要实现这一点,您必须自己调用
.Dispose()
(或使用
调用
),因为当(如果)GC执行此操作时,它无法访问包含日志行的托管成员

b) 不知道,但这并不重要,因为您无论如何都不能为此目的使用终结器

底线是你不能依靠GC来运行代码。这是一种不好的做法,因为你不知道什么时候会发生,加上现在或将来任何地方对对象的引用都会阻止对象被收集并引入bug

您也不应该让c#终结器/析构函数运行代码,因为它们不是用来运行代码的,它们是用来释放非托管资源的,这样机器就不会耗尽。注意,在C#中使用它们是很少见的,因为大多数人的日常工作都是使用托管对象


相反,显式地告诉对象写它的日志,一个名为
Flush
的方法将是一个好名字。或者让它一次只写一行。这将是常见的行为。

这听起来像是一个奇怪的定制解决方案。调查ELMAH(非常少的配置)和log4Net(一些基本的代码更改…。但是“发布”代码已经创建…。将您的消息发布到..Sql Server到一个文本文件到许多其他选项…。我认为在Dispose中会更好-析构函数实际上是
override void Finalize()
方法。您无法控制何时调用它,GC会在受管堆栈已满且位于其链接列表中的下一个堆栈时执行此操作。听起来您正在内存中存储所有消息(
列表
?)只有在会话结束时才写出来。为什么不立即登录?@Corak是的,谢谢,我也认为这是重构过程的一部分,我可能会这样做。你可能知道在没有明确规范的情况下开发时通常是什么情况。你不断添加功能,因为需求会发生变化,然后在某个时候,您需要停止并重构整个类。以前我们不要求此对象写入磁盘日志。这是否适用于ASP.NET会话作用域的单例?我不希望实例在整个会话期间超出作用域。但可能我只是误解了建议的解决方案,即在using block。谢谢你的回答。我不打算使用现有的日志包,主要是因为我想了解如何工作(比如在本例中)。也就是说,当我在类析构函数中时,我用于存储的列表可能已经被收集了?这与我认为GC收集未引用对象的功能相反。关于问题(b)的任何提示?也感谢链接,我会尽快阅读。我建议您阅读以下答案:特别注意:“完全有可能在Dispose()代码中,您试图删除的托管对象(因为您想提供帮助)已不存在”和“因此您需要的是Finalize()告诉Dispose()它不应接触任何托管资源(因为它们可能不再存在)”的方法,也适用于b)这是不相关的,也就是说,无论何时调用终结器都无关紧要,因为您无论如何都无法将终结器用于您的目的。谢谢。这可能与本例无关,但我只是对一般情况感到好奇。