IIS 回收事件后的 .NET 类型初始化异常
本文关键字:NET 类型 初始化 异常 事件 IIS | 更新日期: 2023-09-27 18:32:57
使用 .NET 3.5 C#,我有一个为移动客户端提供服务的 WCF Web 服务。客户端经常使用该服务将数据发送到服务器并接收更新。该服务部署在 IIS 7.5 中,配置为每天早上 0600 时回收。回收通常无缝地工作,客户端继续像往常一样使用该服务。但是,发生了一些事件,其中回收导致应用程序进入有趣的状态,我可以看到日志中充满了类型初始化错误,如下所示。这几乎就像在重叠回收期间发生了一些事情,它没有成功卸载 DLL:
System.NullReferenceException: Object reference not set to an instance of an object.
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary`2.set_Item(TKey key, TValue value)
at Docobo.Keswick.DbAccess.TableData.DataClasses.GetInfo(Type type)
DataClasses 是 IQToolkit 用来查找数据库表名称的内部静态类:
internal static class DataClasses
{
private static readonly Dictionary<Type, DataClassInfo> classInfos = new Dictionary<Type, DataClassInfo>();
public static DataClassInfo GetInfo(Type type)
{
DataClassInfo info;
if (!classInfos.TryGetValue(type, out info))
{
// This is not thread-safe, but that's fine.
// If this class is generated more than once it doesn't matter.
info = new DataClassInfo(type);
classInfos[type] = info;
}
return info;
}
}
手动回收应用程序池解决了此问题。从堆栈跟踪来看,静态只读字段类信息似乎可能是空的,但我不知道这是怎么回事?
异常发生在字典内部,从堆栈跟踪中可以看到:
System.Collections.Generic.Dictionary`2.Insert
几乎发生这种情况的唯一原因是如果您同时访问字典。尝试将其包装在 lock
语句中。
我猜它在回收过程中发生的原因如下。读取字典可能是线程安全的,因此在启动期间发生异常的可能性更高。在回收期间,多个并发的客户端请求可能会暂停,以等待应用程序重新启动。因此,在应用程序重新启动后,会同时进行多次写入尝试。