Click here to Skip to main content
13,045,790 members (46,254 online)
Click here to Skip to main content
Add your own
alternative version

Stats

28K views
12 bookmarked
Posted 1 Jun 2004

Events with Memory in MC++

, 1 Jun 2004
Rate this:
Please Sign up or sign in to vote.
An article on adding memory to events using Managed C++.

Introduction

Delegates are a nice feature of .NET that really make coding callbacks simple. This article is not going to describe how to create delegates and events - there are many other articles on CodeProject that give you this information. One thing that delegates can't do is to remember when an event is invoked so that the data can be sent to any new delegates that get added to the event.

Background

This problem was given to me at work because events were being triggered before all of the parts of the system were created and attached. This lead to some components not having the correct data. This needed to be resolved in a way that was the most generic.

Creating Event Accessors

The first step is to create some delegates and a class with events for them. For the events, the normal declaration was replaced by the accessors for the events.

<PRE lang=mc++>__event void add_E(MyDel* p) { Console::WriteLine("Add E"); pE = static_cast<MyDel*> (Delegate::Combine(pE,p)); } __event void remove_E(MyDel* p) { Console::WriteLine("Remove E"); pE = static_cast<MYDEL*> (Delegate::Remove(pE, p)); } __event void raise_E() { Console::WriteLine("Raise E"); if (pE != 0) pE->Invoke(); }

This creates an event named E. Then a class was created to receive the events.

<PRE lang=mc++>public __gc class EventReceiver { public: void H1() { Console::WriteLine("EventReceiver - H1"); } int H2(int i, float f) { Console::WriteLine("EventReceiver - H2 with args {0} and {1}", i.ToString(), f.ToString()); return 0; } };

Then in the main of this sample, instances of the two classes were created and then delegates attached to the event E. So far, this is just like any other delegate/event project if you were going to create the accessors manually. Of course, the compiler normally creates the accessors for you automatically.

<PRE lang=mc++>EventSource* pE = new EventSource(); EventReceiver* pR = new EventReceiver(); EventReceiver2* pR2 = new EventReceiver2(); // hook event handlers for pR Console::WriteLine("EventReceiver - hooking events"); pE->E += new MyDel(pR, &EventReceiver::H1); pE->E2 += new MyDel2(pR, &EventReceiver::H2); // raise the E event pE->E();

The next step is to give the event a bit of memory to remember when it was raised. If the delegate had variables, then those would have to be saved also. For the event E in this sample, only a bool to say it had been invoked is needed. So, two changes to the code are required - first to the raise_ accessor and then to the add_ accessor.

<PRE lang=mc++>__event void add_E(MyDel* p) { Console::WriteLine("Add E"); pE = static_cast<MyDel*> (Delegate::Combine(pE,p)); if(m_eInvoked == true) p->Invoke(); } __event void raise_E() { Console::WriteLine("Raise E"); if (pE != 0) { m_eInvoked = true; pE->Invoke(); } }

Using this method, the programmer can control which events get this memory enhancement and which do not. For events that are the typical "fire-and-forget" type of events, this might not be needed. For others things, a "fire-and-forget" type of event might reset other variables for other events. An example of this might be paper being inserted into a printer, one event might be to send what paper is available in the printer and another event could be a signal that paper has been removed. The paper removal event could clear a stored variable for what paper is available.

The sample code expands this sample to two receiving instances and two events.

The C# Difference

I looked into using event accessors in C# as well as MC++. I setup class and accessor functions for adding and removing delegates, and then went to add an accessor for raising the event. The compiler would not let me add a function for raising the event. I found this to be strange and puzzling because it is showing that MC++ has more functionality than C#. After looking into it some more, I found that you have to use a custom function to raise the event instead of an accessor. After this was in place, the C# code looked similar to the MC++ code. The code is included in this article but not in the download unless people want it included later.

<PRE lang=mc++>public class EventSource { // private variables for E event private MyDel pE; private bool m_eInvoked; public EventSource() { m_eInvoked=false; } public event MyDel E { add { Console.WriteLine("Add E"); pE += value; if(m_eInvoked==true) value(); } remove { Console.WriteLine("Remove E"); pE -= value; } } public void RaiseE() { m_eInvoked = true; if(pE != null) pE(); } };

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Steve Maier
Instructor / Trainer Rochester Institute of Technology
United States United States
No Biography provided

You may also be interested in...

Comments and Discussions

 
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170713.1 | Last Updated 2 Jun 2004
Article Copyright 2004 by Steve Maier
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid