【问题标题】:WeakReference, WeakEvents: Usefulness for dynamically loaded/unloaded server modules, DLLs?WeakReference、WeakEvents:对动态加载/卸载的服务器模块、DLL 有用吗?
【发布时间】:2015-10-03 03:58:21
【问题描述】:

我正在考虑 WeakReferences 和 WeakEvents 是否适用于服务器模块接口的情况。会不会是个好设计?

但性能问题,当然需要在 WeakEvent 模式中调用和访问 WeakReference,也许也需要

更新:详情

服务器:

  • 有模块管理器,
  • 可以通过共享接口、IModule 加载/卸载 DLL 的实现类,
  • 因此模块管理器创建并保留 IModule 的实例,

模块:

  • 有名称或唯一代码,
  • 需要与其他模块交互,使用他们的方法、属性、事件,

问题在于,当一个模块获取另一个模块的实例(例如从模块管理器中通过名称提供)时,从那时起,无法保证该模块在卸载之前会被垃圾回收。

但是可能有一个给定 IModule 实现的泛型类(WeakRefModule where T: IModule),受限于 IModule,它可以在 IModule 上内部存储 WeakReference。然后给定的模块将通过扩展方法或基于 WeakRefModule 的继承公开其公共方法。在 WeakReference 后面隐藏模块的实例。与属性和事件(WeakEvents)相同。

此类模块始终保证,其他模块无法阻止它进行垃圾收集。

所以问题是,一个好的设计需要多少钱?是否可能存在一些隐藏的问题?

【问题讨论】:

  • 您对 GC 随机删除事件订阅和“模块”是否满意?
  • 为什么要随机删除?模块通常在模块管理器中存储一个实例,因此除非显式卸载,否则模块存在。除非卸载某些模块,否则此类模块之间的 WeakEvents 不会丢失订阅。
  • 我不知道你在说什么。您没有详细说明您的架构。你在说什么样的“模块”?
  • 哦,对不起,问题是,当我谈到细节时,通常我的问题被关闭为不是问题,所以我避免了:)。我会用更多细节更新问题本身......
  • 是的,这确实是必要的。现在很抽象。

标签: c# .net interface


【解决方案1】:

这种设计基本上是可行的。您需要确保对要保持加载的模块有强引用。否则 GC 将不确定地杀死弱引用。

一个问题是模块不能依赖其他模块。如果一个模块被卸载并且弱引用变为空,对该模块的调用要么失败要么什么都不做。此外,ref 变为 null 的时间点是不确定的。

我根本不会在这里使用弱引用。您可以创建一个仅委托给另一个 IModule 的包装器 IModule。然后,您可以在要卸载模块时清除该包装器。

class WrappedModule : IModule {
 IModule inner;

 public void Dispose() { inner = null; }

 void IModule.SomeMeth() {
  if (inner == null) throw ...;
  else inner.SomeMeth();
 }
}

现在您可能会泄漏一个包装器对象,但它很小。你不会领导真正的模块。

模块永远不会直接访问其他模块。相反,它们被传递给这个“句柄”类。可以随时禁用句柄。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-12
    • 1970-01-01
    • 2012-11-07
    • 2010-11-23
    • 2012-05-08
    • 2015-12-14
    相关资源
    最近更新 更多