<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: .Net EventHandlers &#8211; Best Practices</title>
	<atom:link href="http://www.danrigsby.com/blog/index.php/2008/03/09/net-eventhandlers-best-practices/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.danrigsby.com/blog/index.php/2008/03/09/net-eventhandlers-best-practices/</link>
	<description>Developer.Speaker.Blogger</description>
	<lastBuildDate>Sun, 14 Aug 2011 06:09:27 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: Jack</title>
		<link>http://www.danrigsby.com/blog/index.php/2008/03/09/net-eventhandlers-best-practices/comment-page-1/#comment-3309</link>
		<dc:creator>Jack</dc:creator>
		<pubDate>Tue, 11 Aug 2009 17:38:53 +0000</pubDate>
		<guid isPermaLink="false">http://www.danrigsby.com/blog/index.php/2008/03/09/net-eventhandlers-best-practices/#comment-3309</guid>
		<description>This is a fantastic post.  I tested this with a test program and it cleans up the events nicely.

&lt;code&gt;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Event_Firing_TEST_Profiler
{
	public partial class Form1 : Form
	{
		public static int totalExecutions = 0;

		public Form1()
		{
			InitializeComponent();
		}

		Record _record = new Record();
		Queue _watchers = new Queue();

		private void timer_Tick(object sender, EventArgs e)
		{
			_record.ID++;
			for(int i = 0; i  10000)
			{
				for(int i = 0; i &lt; _watchers.Count * 0.75; i++)
				{
				   RecordWatcher watcher = _watchers.Dequeue();
				   //watcher.Dispose();
				}
				_record.ClearEvents();
				
			}

			_txtInfo.Text = _record.Info;
		}

		private void Form1_Load(object sender, EventArgs e)
		{
			timer.Enabled = true;
		}
	}

	class Record
	{
		public delegate void UpdateHandler(object sender, EventArgs e);
		private event UpdateHandler _onUpdate;

		public event UpdateHandler OnUpdate
		{
			add { _onUpdate += value; }
			remove { _onUpdate -= value; }
		}

		public void ClearEvents()
		{
			_onUpdate = null;
		}

		private int _id;
		private int _firedThisRound;
		private TimeSpan _fireSpan;
		public int ID
		{
			get { return _id; }
			set
			{
				_id = value;
				_firedThisRound = 0;
				DateTime start = DateTime.Now;
				FireEventOnCallerThread(_onUpdate, this, EventArgs.Empty);
				DateTime end = DateTime.Now;
				_fireSpan = end.Subtract(start);
			}
		}
		public void IncrementFired()
		{
			_firedThisRound++;
		}
		public string Info
		{
			get
			{
				int dLength = 0;
				if(_onUpdate != null)
				{
					MulticastDelegate md = _onUpdate;
					Delegate[] d = md.GetInvocationList();
					dLength = d.Length;
				}
				return &quot;delegate.count = &quot; + dLength.ToString(&quot;#,0&quot;) + &quot;, fired this round = &quot; + _firedThisRound.ToString(&quot;#,0&quot;) + &quot;, fireSpan = &quot; + _fireSpan.TotalSeconds.ToString(&quot;#,0.000&quot;) + &quot;, totalExecutions = &quot; + Form1.totalExecutions.ToString(&quot;#,0&quot;);
			}
		}

		public static void FireEventOnCallerThread(MulticastDelegate md, object sender, object e)
		{
			// If there is no event, then we have nothing to do
			if(md == null) return;

			// Create an argument array for the function
			object[] args = new object[] { sender, e };

			// Loop each delegate in the invocation list
			foreach(Delegate d in md.GetInvocationList())
			{
				ISynchronizeInvoke isi = d.Target as ISynchronizeInvoke;
				if(isi != null &amp;&amp; isi.InvokeRequired)
					isi.BeginInvoke(d, args);
				else
					d.DynamicInvoke(args);
			}
		}
	}

	class RecordWatcher : IDisposable
	{
		public Record _record;
		public RecordWatcher(Record record)
		{
			_record = record;
			_record.OnUpdate += new Record.UpdateHandler(_record_OnUpdate);
		}

		void _record_OnUpdate(object sender, EventArgs e)
		{
			Form1.totalExecutions++;
			((Record)sender).IncrementFired();
		}

		public void Dispose()
		{
			_record.OnUpdate -= new Record.UpdateHandler(_record_OnUpdate);
		}
	}
}
&lt;/code&gt;</description>
		<content:encoded><![CDATA[<p>This is a fantastic post.  I tested this with a test program and it cleans up the events nicely.</p>
<p><code><br />
using System;<br />
using System.Collections.Generic;<br />
using System.ComponentModel;<br />
using System.Data;<br />
using System.Drawing;<br />
using System.Text;<br />
using System.Windows.Forms;</p>
<p>namespace Event_Firing_TEST_Profiler<br />
{<br />
	public partial class Form1 : Form<br />
	{<br />
		public static int totalExecutions = 0;</p>
<p>		public Form1()<br />
		{<br />
			InitializeComponent();<br />
		}</p>
<p>		Record _record = new Record();<br />
		Queue _watchers = new Queue();</p>
<p>		private void timer_Tick(object sender, EventArgs e)<br />
		{<br />
			_record.ID++;<br />
			for(int i = 0; i  10000)<br />
			{<br />
				for(int i = 0; i &lt; _watchers.Count * 0.75; i++)<br />
				{<br />
				   RecordWatcher watcher = _watchers.Dequeue();<br />
				   //watcher.Dispose();<br />
				}<br />
				_record.ClearEvents();</p>
<p>			}</p>
<p>			_txtInfo.Text = _record.Info;<br />
		}</p>
<p>		private void Form1_Load(object sender, EventArgs e)<br />
		{<br />
			timer.Enabled = true;<br />
		}<br />
	}</p>
<p>	class Record<br />
	{<br />
		public delegate void UpdateHandler(object sender, EventArgs e);<br />
		private event UpdateHandler _onUpdate;</p>
<p>		public event UpdateHandler OnUpdate<br />
		{<br />
			add { _onUpdate += value; }<br />
			remove { _onUpdate -= value; }<br />
		}</p>
<p>		public void ClearEvents()<br />
		{<br />
			_onUpdate = null;<br />
		}</p>
<p>		private int _id;<br />
		private int _firedThisRound;<br />
		private TimeSpan _fireSpan;<br />
		public int ID<br />
		{<br />
			get { return _id; }<br />
			set<br />
			{<br />
				_id = value;<br />
				_firedThisRound = 0;<br />
				DateTime start = DateTime.Now;<br />
				FireEventOnCallerThread(_onUpdate, this, EventArgs.Empty);<br />
				DateTime end = DateTime.Now;<br />
				_fireSpan = end.Subtract(start);<br />
			}<br />
		}<br />
		public void IncrementFired()<br />
		{<br />
			_firedThisRound++;<br />
		}<br />
		public string Info<br />
		{<br />
			get<br />
			{<br />
				int dLength = 0;<br />
				if(_onUpdate != null)<br />
				{<br />
					MulticastDelegate md = _onUpdate;<br />
					Delegate[] d = md.GetInvocationList();<br />
					dLength = d.Length;<br />
				}<br />
				return "delegate.count = " + dLength.ToString("#,0") + ", fired this round = " + _firedThisRound.ToString("#,0") + ", fireSpan = " + _fireSpan.TotalSeconds.ToString("#,0.000") + ", totalExecutions = " + Form1.totalExecutions.ToString("#,0");<br />
			}<br />
		}</p>
<p>		public static void FireEventOnCallerThread(MulticastDelegate md, object sender, object e)<br />
		{<br />
			// If there is no event, then we have nothing to do<br />
			if(md == null) return;</p>
<p>			// Create an argument array for the function<br />
			object[] args = new object[] { sender, e };</p>
<p>			// Loop each delegate in the invocation list<br />
			foreach(Delegate d in md.GetInvocationList())<br />
			{<br />
				ISynchronizeInvoke isi = d.Target as ISynchronizeInvoke;<br />
				if(isi != null &amp;&amp; isi.InvokeRequired)<br />
					isi.BeginInvoke(d, args);<br />
				else<br />
					d.DynamicInvoke(args);<br />
			}<br />
		}<br />
	}</p>
<p>	class RecordWatcher : IDisposable<br />
	{<br />
		public Record _record;<br />
		public RecordWatcher(Record record)<br />
		{<br />
			_record = record;<br />
			_record.OnUpdate += new Record.UpdateHandler(_record_OnUpdate);<br />
		}</p>
<p>		void _record_OnUpdate(object sender, EventArgs e)<br />
		{<br />
			Form1.totalExecutions++;<br />
			((Record)sender).IncrementFired();<br />
		}</p>
<p>		public void Dispose()<br />
		{<br />
			_record.OnUpdate -= new Record.UpdateHandler(_record_OnUpdate);<br />
		}<br />
	}<br />
}<br />
</code></p>
]]></content:encoded>
	</item>
</channel>
</rss>

