我创建了一个双工服务(NetTcpBinding),类似于这个例子:我使用了发布-订阅模式,对于来自新客户端的每个连接请求,它都会创建服务的一个新实例(包含不同的回调)。在本例中,回调通过事件和委托调用。
现在我要修改这个例子:假设我们不想立即响应客户机的请求,也就是说,假设我们想在一定时间间隔之后调用回调方法。在这种情况下,我需要保持对回调方法的引用.但是,如果在此期间,一些客户断开了连接,会发生什么呢?服务实例被破坏了,我们甚至失去了回调.
我写了这个例子:
MySingletonTable是存储对回调方法的引用的数据结构;SampleService不是服务,而是模拟服务的实例;
公共委托void ProcessingHandler(字符串项,双价格,双重更改);公共类MySingletonTable {私有静态易失性MySingletonTable m_Instance;私有静态对象syncRoot =新对象();私有静态Dictionary pointersToHandlers;私有MySingletonTable() { pointersToHandlers =新Dictionary();} //返回该类的单例实例。公共静态MySingletonTable实例{ get { if (m_Instance == null) { lock (syncRoot) { if (m_Instance == null) m_Instance =新MySingletonTable();}返回m_Instance;}/表中的条目数。公共int计数{ get { lock (syncRoot) {返回pointersToHandlers.Count;} //添加处理程序。公共void (string,ProcessingHandler处理程序){ lock (syncRoot) { if (!pointersToHandlers.ContainsKey(id)) pointersToHandlers.Add(id,处理程序);} //从表中获取一个处理程序。public ProcessingHandler GetHandler(string id) { ProcessingHandler处理程序= null;ProcessingHandler (syncRoot) { if (pointersToHandlers.ContainsKey(id))处理程序= pointersToHandlersid;}返回处理程序;} //删除指定的处理程序。公共bool删除(String id) { lock (syncRoot) {返回pointersToHandlers.Remove(id);}} //此类模拟服务。公共类SampleService {私有静态int计数器= 0;私有int service_i = ++counter;MySingletonTable引用= MySingletonTable.Instance;公共SampleService(string id) { reference.Add(id,PriceChange);}私有空PriceChange(字符串项目,双价,双更改){ //调用回调/.Console.WriteLine("service_i {0}:{1} {2} {3}",service_i,项目,价格,变化);}类程序{静态空主(string[] args) { SampleService s1 =新SampleService("abc");SampleService s2 =新SampleService("def");MySingletonTable table = MySingletonTable.Instance;ProcessingHandler处理程序=空;处理程序= table.GetHandler("abc");处理程序(“项目一”,10,20);处理程序= table.GetHandler("def");处理程序(“项目二”,30,40);Console.ReadLine();}显然,我不能显式地销毁这个示例中模拟的两个服务实例。但是,如果s1和s2是与两个不同客户端相关的服务的两个实例,会发生什么情况呢?
发布于 2012-06-25 21:08:23
如果您的委托存储在pointersToHandlers中,那么它将保存在您的对象上,因此它永远不会被垃圾收集,也不会像您所说的那样被“销毁”。实际上,您现在也有内存泄漏。
当客户端断开连接时(或当您期望对象被销毁时),您将需要从列表中删除委托。不知道为什么不使用事件,但这是另一个问题。即使您确实使用了事件,一旦完成,您仍然需要断开连接,这样就不会出现这种情况。
发布于 2012-06-25 22:08:17
好的,您正在将局部变量S1和S2设置为null。然而,字典仍然有对象的地址。当您执行s1 = null时,新操作符创建的s1不会被删除,这就是为什么以后调用处理程序仍然有效的原因。这和做同样的事情是一样的:
var s1 = new SampleService("aa");
var handler = s1;
s1 = null;处理程序仍在引用创建的对象。
发布于 2014-04-11 01:10:06
不如..。
if (kDelegate.Target != null) kDelegate();https://stackoverflow.com/questions/11197079
复制相似问题