`
zealotds
  • 浏览: 122379 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

Events, references, garbage collecting, memory leaks and weak delegates

    博客分类:
  • .net
阅读更多
20091209 标题更新更改了标题,囊括了原作者的另一篇短文

在关于服务、容器的编程(IOC实现)中,随着事件的引入,事情就会变的复杂起来。你需要把两个服务通过事件连接起来。但在平静的表面下,隐藏着可怕的内存泄露。事件并不适合于松散耦合的环境,值得大家格外注意。

这就是所谓的lapsed listener问题

下边是摘自Steve Maine关于该问题的一段话:

引用
当对象订阅了一个事件却导致了它超出了(程序预期的)控制范围,失控的监听器(lapsed listener)就会产生——该对象不会被GC回收,因为它的引用始终存在于事件的Invoke列表当中。所有的事件订阅者都会被GC认为仍然存在引用。因此它们不会被回收,直到事件本身的消失(通常是程序关闭的时候)。举例来说,当你实现一个观察者模式时,你就必须小心处理相关事件和其订阅者的生命周期。否则,那些对象就会超出你的预期,长时间地驻留。这时候Unsubscribe()就是你的朋友了。


事实上,.Net委托(delegate)就是一种观察者模式的实现。下边是一个对象可以被正确释放的例子:
StoopidObject object = new StoopidObject();
GC.Collect();
GC.WaitForPendingFinalizers();


下边的例子中虽然没有明显的队Observer的引用,但它却不能被释放:
Observer observer = new Observer();
Subject subject = new Subject();
subject.SomethingHappened += new EventHandler(observer.subject_SomethingHappened);
GC.Collect();
GC.WaitForPendingFinalizers();


一些社区里的朋友想出了一种“弱委托(weak delegates)”的方法:

原文作者采用了另外的方法,因为以上的方案使用了弱委托,但不能满足要求:在被GC回收之前,监听器还会不断收到事件的通知,你也不知道什么时候才会下一次GC。所以,在弱委托的方案中你必须接受你的对象不会立刻被释放这一事实。

原作者想要立刻停止受到事件通知,要求监听器主动断开连接。一种简单的方案就是在Dispose方法中完整该动作,因为在你想要释放一个对象的时候,你总会去调用Dispose方法。

下边的代码摘自原作者的测试代码:
另外作者在另一篇文章中提到了一种WeakDelegate的实现,这里只提供基本的实现代码仅供参考:

public class Subject
{
	private ArrayList _Delegates;

	public Subject()	{	}

	public event EventHandler SomethingHappened
	{
		add
		{
			if (_Delegates == null)
				_Delegates = new ArrayList(1);

			// Reference the subscriber via a "short" weak reference.  If the 
			// subscriber is not reachable by any other rooted reference path, 
			// it will be collected!
			WeakReference wr = new WeakReference(value);
			_Delegates.Add(wr);
		}
		remove
		{
			if (_Delegates == null)
				return;

			// Loop through the list of subscribers, removing any whose 
			// instance-identity matches the unsubscribe-request.  Also 
			// take the opportunity, while we're at it, to remove any 
			// deceased weak refs. (Iterate in reverse, to avoid skipping.)
			for (int i = _Delegates.Count-1; i >= 0; --i)
			{
				WeakReference wr = (WeakReference) _Delegates[i];
				if (!wr.IsAlive || Object.ReferenceEquals(value, wr.Target))
					_Delegates.RemoveAt(i);
			}
		}
	}

	public void Notify()
	{
		Console.WriteLine("Notifying");

		if (_Delegates == null)
			return;

		// Enumerate the list of delegates; dereference and invoke each one.
		for (int i = _Delegates.Count-1; i >= 0; --i)
		{
			WeakReference wr = (WeakReference) _Delegates[i];
			if (wr.IsAlive)
			{
				EventHandler handler = wr.Target as EventHandler;
				if (handler != null)
					handler(this, EventArgs.Empty);
			}
			else
			{
				_Delegates.RemoveAt(i);
			}
		}
	}
}




强制取消事件订阅
原文地址: Forcing event unsubscription

根据笔者经验,事件是.net程序中的主要资源泄漏原因。开发人员应该对其进行两倍甚至三倍的检查。每当你向一个事件添加订阅时,你就应当想到需不需要或者什么时候去取消这个订阅。如果该订阅必须摘除(否则会引起泄漏),那就趁你还没忘记以前马上添加取消订阅的代码。

通常情况下,可以在Dispose方法中完成。

不要忘记事件发起者(Subject)将始终保持其观察者(Observer/Listenser)的引用(造成其不被释放):


为了保证Listenser被释放,推荐的做法是(主动)取消事件订阅。但当你已经明确知道某个事件不会再发送通知消息并希望事件的订阅者能够被释放,你可以通过以下代码达到目的:

if (SomeEvent != null)
{
  foreach (EventHandler handler in SomeEvent.GetInvocationList())
    SomeEvent -= handler;
}


更简单地:
SomeEvent = null


0
0
分享到:
评论

相关推荐

    Android代码-android-weak-handler

    Android Weak Handler Memory safer implementation of android.os.Handler Problem Original implementation of Handler always keeps hard reference to handler in queue of execution. Any object in Message or...

    java面试题英文版及其答案

    Once an object is deemed unreachable, the garbage collector reclaims the associated memory, preventing memory leaks. 7. What is a Java package, and why is it used?Answer: A Java package is a ...

    Efficient MIDP Programming

    - **Memory Profiling**: Use memory profiling tools to identify memory leaks and excessive object creation. - **Memory Management**: Implement strategies to free up memory when it is no longer needed. ...

    Image Processing for Computer Graphics and Vision (2rd Edition)

    1.4 Comments and References 2 Signal Theory 2.1 Abstraction Paradigms 2.2 Mathematical Models for Signals 2.3 Linear Representation of Signals 2.4 Operations on Signals 2.5 Sampling Theory 2.6 ...

    Selected.Topics.in.Cplusplus.15117

    C++ has stack memory and heap memory. You need to control where you want to put your objects. It has constructors and destructors. You need to know when and how they are called. Then it has multiple ...

    references.zip

    references/detection/engine.py , references/detection/utils.py 和 references/ detection/transforms.py

    Eclipse Memory Analyzer1.8.1&安装使用指南.zip

    Eclipse Memory Analyzer(MAT)是一款强大的Java内存分析工具,它被广泛用于诊断和解决Java应用程序中的内存泄漏问题。MAT 1.8.1是适用于macOS的特定版本,旨在帮助开发者深入理解并优化他们的Java应用内存使用情况...

    CUDA Reference from NVIDIA official site.

    `cudaMemcpy` copies memory between the host and device, or between different regions of device memory. This function is fundamental for transferring data between the CPU and GPU. **1.5.11 cudaMemcpy...

    Microsoft Visual C# 2010 Step by Step Mar 2010

    14 Using Garbage Collection and Resource Management 279 Part III Creating Components 15 Implementing Properties to Access Fields 295 16 Using Indexers 315 17 Interrupting Program Flow and Handling...

    Array And Phased Array Antenna Basics

    The Union of Electricity and Magnetism 8 1.3 Radiation by Accelerated Charge 10 1.4 Reactive and Radiating Electromagnetic Fields 18 References 18 2 Antennas 19 2.1 The Early History of Antennas 19 ...

    一个用户管理c++设计课题

    This assignment will give you practice building some simple classes and making use of basic C++ features including: encapsulation, references, dynamic memory allocation, simple constructors and ...

    iOS Programming: The Big Nerd Ranch Guide (4th Edition) 2014 epub

    ARC and strong and weak references Handling touch events and gestures Toolbars, navigation controllers, and split view controllers Using Auto Layout to scale user interfaces Using Dynamic Type to ...

    hibernate4.3.5references chm文档

    hibernate4.3.5references chm文档

    Pattern Recognition with Neural Networks in C++

    References And Bibliography Chapter 2—Neural Networks: An Overview 2.1 Motivation for Overviewing Biological Neural Networks 2.2 Background 2.3 Biological Neural Networks 2.4 ...

    Audio Signal Processing and Coding (高清PDF)

    【下载说明】 此为此通信... It includes a comprehensive bibliography with over 600 references, computer exercises, and MATLAB-based projects for use in EE multimedia, computer science, and DSP courses

    Analog and Digital Signals and Systems

    references for the books and journals (over 160 references) are listed in the bibliography section. At the undergraduate level, most signal analysis courses do not require probability theory. Only, a ...

    Asset Cleaner PRO - Clean - Find References

    Feature 1 - Project Cleaner: 1、Actions for unused files 2、Enhanced Project View Feature 2 - Find References: 1、Find references, usages, relationships easily in ...2、Explore usages & references

    Python库 | wagtail_references-0.0.2.tar.gz

    《Python库 wagtail_references-0.0.2详解》 在Python编程领域,库的使用是提高开发效率和代码质量的重要手段。今天我们要探讨的是一个名为`wagtail_references`的Python库,版本号为0.0.2,它封装了一些特定的功能...

    Fundamentals of wavelets theory algorithms and applications

    2.3 Basis Functions, Orthogonality and Biothogonality. 2.4 Local Basis and Riesz Basis. 2.5 Discrete Linear Normed Space. 2.6 Approximation by Orthogonal Projection. 2.7 Matrix Algebra and Linear ...

Global site tag (gtag.js) - Google Analytics