1

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

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

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

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

b] 何时为会话范围的对象调用析构函数?只有当会话在服务器上过期时?

4

2 回答 2

1

我还建议使用一些现有的日志记录包。如果您确实决定自己这样做,并且只是为了将来考虑:

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

我不想重复推荐的模式,所以请参阅https://stackoverflow.com/a/1943856/2586804

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

b)不知道,但这没关系,因为无论如何您都不能为此目的使用终结器。

底线是你不能依赖 GC 来为你运行代码。这是不好的做法,因为您不知道它何时会发生,再加上现在或将来在任何地方对对象的任何引用都会阻止对象被收集并引入错误。

您也不应该让 c# Finalizers/Destructors 来运行代码,因为这不是它们的用途,它们是用于释放非托管资源以便机器不会耗尽。请注意,在 C# 中很少使用它们,因为大多数人的日常工作都是使用托管对象。

相反,明确告诉对象写入它的日志,调用的方法Flush将是一个好名字。或者只是让它一次写一行。这将是通常的行为。

于 2013-07-18T15:49:58.133 回答
1

要完成此操作,请实现IDisposable,然后将记录器的实例包装在using块中,这将保证在记录器上调用 dispose 方法。

于 2013-07-18T15:09:00.593 回答