How do you implement a message queuing system?
-
I am trying to implement a message queuing system in my applicaton. I have a main application which dynamically loads plugins that implement a required interface. In order to send out message to and from plugins I have an OnMessage() function that receives any message sent to it. Here is how it works. The main application has a central object called lets say System which the plugins have access to. One the the methods of system allows you to create a message. IMessage message = System.NewMessage() ... message.Send(); All messages are to be created, dispatched, and disposed of my the system object. How should I approach this problem. I'm sure I will need a message queue, but I am not sure about the rest. Any ideas welcome. PS: I don't want to use MS Message queue and all communication is only on the local machine.
-
I am trying to implement a message queuing system in my applicaton. I have a main application which dynamically loads plugins that implement a required interface. In order to send out message to and from plugins I have an OnMessage() function that receives any message sent to it. Here is how it works. The main application has a central object called lets say System which the plugins have access to. One the the methods of system allows you to create a message. IMessage message = System.NewMessage() ... message.Send(); All messages are to be created, dispatched, and disposed of my the system object. How should I approach this problem. I'm sure I will need a message queue, but I am not sure about the rest. Any ideas welcome. PS: I don't want to use MS Message queue and all communication is only on the local machine.
Rather than having IMessage implement the sending it'd probably be easier to let the plugin send the message since it should contain a reference to the "System" object. If all Plugins derive from a base-class then you can implement a "SendMessage" function which will accept an IMessage and simply call a routine on the System object to add the message to it's internal Queue (you can use a Generic Queue or whatever for this). So basically:
interface IMessage
{
// Properties
}
abstract class Plugin
{
System parent;
virtual void SendMessage(IMessage message)
{
this.parent.OnMessage(message);
}
}Et voila, I know that you said all plug-ins implement a particular interface but might I suggest they instead derive from a base-class because then you can easily add stuff like the above to it. If you were only providing an interface then the plugin writer would have to write the SendMessage function each time they write a plugin. If you need to store the messages then I think there's a Queue Collection in the System.Collections and System.Collections.Generic namespaces (first is "weakly-typed", secondly can be generically typed to IMessage).
The Welsh will always support two teams: The Welsh, and anyone playing England :)
-
Rather than having IMessage implement the sending it'd probably be easier to let the plugin send the message since it should contain a reference to the "System" object. If all Plugins derive from a base-class then you can implement a "SendMessage" function which will accept an IMessage and simply call a routine on the System object to add the message to it's internal Queue (you can use a Generic Queue or whatever for this). So basically:
interface IMessage
{
// Properties
}
abstract class Plugin
{
System parent;
virtual void SendMessage(IMessage message)
{
this.parent.OnMessage(message);
}
}Et voila, I know that you said all plug-ins implement a particular interface but might I suggest they instead derive from a base-class because then you can easily add stuff like the above to it. If you were only providing an interface then the plugin writer would have to write the SendMessage function each time they write a plugin. If you need to store the messages then I think there's a Queue Collection in the System.Collections and System.Collections.Generic namespaces (first is "weakly-typed", secondly can be generically typed to IMessage).
The Welsh will always support two teams: The Welsh, and anyone playing England :)
Okay I follow what your saying and it has good merit. I am trying to find more info on the actual message queuing part of the process that you mention at the end of your comment. So, the System has a message queue that messages get added to. 1. They need to be depatched 2. They need to be disposed of. 3. What to do it no one consumes the message ( send it again, ?) 4. Is dispatching done on a thread or timer or what? I hope that makes sense.
-
Okay I follow what your saying and it has good merit. I am trying to find more info on the actual message queuing part of the process that you mention at the end of your comment. So, the System has a message queue that messages get added to. 1. They need to be depatched 2. They need to be disposed of. 3. What to do it no one consumes the message ( send it again, ?) 4. Is dispatching done on a thread or timer or what? I hope that makes sense.
Are your plugin objects sending messages to the System object from various threads? Why do your message objects need to be disposed of?
-
Are your plugin objects sending messages to the System object from various threads? Why do your message objects need to be disposed of?
I mentioned threads just because I am not sure how to implement what I am asking. I was thinking that if the message queuing framework ran in a thread it wouldn't bogg down the main application thread. When I said disposed I was actaull thinking of several issues. 1) A message has a lifespan where it is considered useful. If I send out a message once and none one consumes it, is it considered end of life, or should it be re-sent a number of times. (assuming that for reason someone may have missing receiving it.) 2) Some messages will target specific plugins where as some messages may have several intended recipients. So the system must be in control of when the message gets removed from the queue. 3) If a message object is created it should be disposed (menory freed). I know garabe collection will eventually get it. (Also my message consist of an object that I have ceated to pass data back and forth) -- modified at 2:19 Sunday 25th June, 2006
-
I mentioned threads just because I am not sure how to implement what I am asking. I was thinking that if the message queuing framework ran in a thread it wouldn't bogg down the main application thread. When I said disposed I was actaull thinking of several issues. 1) A message has a lifespan where it is considered useful. If I send out a message once and none one consumes it, is it considered end of life, or should it be re-sent a number of times. (assuming that for reason someone may have missing receiving it.) 2) Some messages will target specific plugins where as some messages may have several intended recipients. So the system must be in control of when the message gets removed from the queue. 3) If a message object is created it should be disposed (menory freed). I know garabe collection will eventually get it. (Also my message consist of an object that I have ceated to pass data back and forth) -- modified at 2:19 Sunday 25th June, 2006
smesser wrote:
I mentioned threads just because I am not sure how to implement what I am asking. I was thinking that if the message queuing framework ran in a thread it wouldn't bogg down the main application thread.
Ok. My DelegateQueue[^] class may help out if you need a message queue. It's not a message queue per se, but it can provide basic functionality that you may need to build upon. Sending messages from the plugin to your system object will be pretty straightforward. Each plugin has a reference to the system object so that it can send it messages. Sending messages from the system object back to the plugins may be a little more tricky. The system object will need to keep track of all of the plugins. If the system object is running in its own thread, it will need to marshal its events to the plugins' thread. All this is kinda vague, though. Can you describe more of what you want to accomplish with the system and plugins sending messages back and forth? When are the messages sent? I guess I just need more details overall.
-
smesser wrote:
I mentioned threads just because I am not sure how to implement what I am asking. I was thinking that if the message queuing framework ran in a thread it wouldn't bogg down the main application thread.
Ok. My DelegateQueue[^] class may help out if you need a message queue. It's not a message queue per se, but it can provide basic functionality that you may need to build upon. Sending messages from the plugin to your system object will be pretty straightforward. Each plugin has a reference to the system object so that it can send it messages. Sending messages from the system object back to the plugins may be a little more tricky. The system object will need to keep track of all of the plugins. If the system object is running in its own thread, it will need to marshal its events to the plugins' thread. All this is kinda vague, though. Can you describe more of what you want to accomplish with the system and plugins sending messages back and forth? When are the messages sent? I guess I just need more details overall.
I will have a look at your link. The system object has a plugin manager which loads the plugins and will be used to dispatch all messages. I am not sure what you mean by
Leslie Sanford wrote:
If the system object is running in its own thread, it will need to marshal its events to the plugins' thread.
The system object will be running in the main application thread, which will load all the plugins. Also, I am a C++ coder semi-recently moved to C# so marshalling is still confusing to me. I will now try to get a better explaination of what I am trying to accomplish. To get the over-all picture you can see this site www.xmission.com/~smesser. The project shown is using C++ and GDI+, currently my site is out of date as now I am using C# and WinFX. Basically, I am trying to make a complete framework which has controls and a base functionality so that via XML and plugins you can describe and add any functionality you need. I am targeting Home Theater PC. So, when a plugin loads it can have the following: 1) panels will cantain controls. ( buttons, graphics, list boxes etc ) All drawn using WinFx. All messages and events will be sent to the system object for dispersal thoughtout the application. 2) Messages are needed to allow control of the plugins. Let's say there is a music plugin that has the functionality of Play, Stop, Pause, load playlist etc. Some one else could write a plugin to control this music plugin or replace it. So, this control plugin could create a panel with controls on it, get a music list from the database ( another plugin ) display ID3Tag info about each file, show an album cover etc, then send a playlist message to the music plugin followed by a play-all message. A plugin could publish any of this infomation so that other plugins could subscribe to the music module data feed and use it. 3) The system object needs to handle all the message passing as most of the application functionality will be added via plugins. Even the application core functionality will be added using functionality. By core fucntionality I mean: a. Database access b. create controls, panels, etc. c. Other fundamental operaations like load panel, display panel etc. 4) I guess messages need to be sent as they happen
-
I will have a look at your link. The system object has a plugin manager which loads the plugins and will be used to dispatch all messages. I am not sure what you mean by
Leslie Sanford wrote:
If the system object is running in its own thread, it will need to marshal its events to the plugins' thread.
The system object will be running in the main application thread, which will load all the plugins. Also, I am a C++ coder semi-recently moved to C# so marshalling is still confusing to me. I will now try to get a better explaination of what I am trying to accomplish. To get the over-all picture you can see this site www.xmission.com/~smesser. The project shown is using C++ and GDI+, currently my site is out of date as now I am using C# and WinFX. Basically, I am trying to make a complete framework which has controls and a base functionality so that via XML and plugins you can describe and add any functionality you need. I am targeting Home Theater PC. So, when a plugin loads it can have the following: 1) panels will cantain controls. ( buttons, graphics, list boxes etc ) All drawn using WinFx. All messages and events will be sent to the system object for dispersal thoughtout the application. 2) Messages are needed to allow control of the plugins. Let's say there is a music plugin that has the functionality of Play, Stop, Pause, load playlist etc. Some one else could write a plugin to control this music plugin or replace it. So, this control plugin could create a panel with controls on it, get a music list from the database ( another plugin ) display ID3Tag info about each file, show an album cover etc, then send a playlist message to the music plugin followed by a play-all message. A plugin could publish any of this infomation so that other plugins could subscribe to the music module data feed and use it. 3) The system object needs to handle all the message passing as most of the application functionality will be added via plugins. Even the application core functionality will be added using functionality. By core fucntionality I mean: a. Database access b. create controls, panels, etc. c. Other fundamental operaations like load panel, display panel etc. 4) I guess messages need to be sent as they happen
smesser wrote:
The system object will be running in the main application thread, which will load all the plugins. Also, I am a C++ coder semi-recently moved to C# so marshalling is still confusing to me.
Marshaling just means that you take an event that happened on one thread and handle it on another thread. I'm not familiar with WinFx, so I can't comment on it specifically. Are you familiar with C# events? One possibility is for the plugins to implement events. When something interesting happens to a plugin, it raises an event. The system object could subscribe to these events and respond to them accordingly. That takes care of the communication that takes place from the plugin to the system object. To go from the system to the plugin, the system could keep track of the plugins and simply call a method on them when it needs to tell a plugin something important. Since I'm not familiar with WinFx, I'm not really sure how you would do this, but if you have a main window, you could use it's message pump for handling the messages. With Windows Forms, you use the Invoke and BeginInvoke methods. So since your system object runs on your application thread, you could think of the Window itself as being this system object, the object that receives messages from your plugins. Well, I hope some of this is helpful. Plugins are a bit of a mystery to me here, so I'm kind of guessing in giving you advice.
-
smesser wrote:
The system object will be running in the main application thread, which will load all the plugins. Also, I am a C++ coder semi-recently moved to C# so marshalling is still confusing to me.
Marshaling just means that you take an event that happened on one thread and handle it on another thread. I'm not familiar with WinFx, so I can't comment on it specifically. Are you familiar with C# events? One possibility is for the plugins to implement events. When something interesting happens to a plugin, it raises an event. The system object could subscribe to these events and respond to them accordingly. That takes care of the communication that takes place from the plugin to the system object. To go from the system to the plugin, the system could keep track of the plugins and simply call a method on them when it needs to tell a plugin something important. Since I'm not familiar with WinFx, I'm not really sure how you would do this, but if you have a main window, you could use it's message pump for handling the messages. With Windows Forms, you use the Invoke and BeginInvoke methods. So since your system object runs on your application thread, you could think of the Window itself as being this system object, the object that receives messages from your plugins. Well, I hope some of this is helpful. Plugins are a bit of a mystery to me here, so I'm kind of guessing in giving you advice.
Yes, I am familiar with events. I am wanting my system object to be the place where plugins subscribe to my application events. I believe I know who to handle the events from Winfx. The system object would translate them into events my application understands. Continuing with the music plugin example, Lets say a song ends, it would send a message in the form of an event "music.event.endofsong" to the system object, a message/event could include or not data along with it. A plugin could subscribe to "music.event.*" The system would forword/dispatch this message to anyone interested or that has subscribed and then remove it from the queue. I guess what I am really trying to do is create a message/event pump like the windows forms message pump you mentioned. Thanks for the dialog as it is more helpful than you realize. You make me think about this in ways that I may overlook. It's always nice to bouce idea around.
-
Yes, I am familiar with events. I am wanting my system object to be the place where plugins subscribe to my application events. I believe I know who to handle the events from Winfx. The system object would translate them into events my application understands. Continuing with the music plugin example, Lets say a song ends, it would send a message in the form of an event "music.event.endofsong" to the system object, a message/event could include or not data along with it. A plugin could subscribe to "music.event.*" The system would forword/dispatch this message to anyone interested or that has subscribed and then remove it from the queue. I guess what I am really trying to do is create a message/event pump like the windows forms message pump you mentioned. Thanks for the dialog as it is more helpful than you realize. You make me think about this in ways that I may overlook. It's always nice to bouce idea around.
smesser wrote:
Thanks for the dialog as it is more helpful than you realize. You make me think about this in ways that I may overlook. It's always nice to bouce idea around.
I'm glad it's helpful. :-) It's got me thinking, too. I think the messaging you've described may be complex enough that using C# events may not be appropriate. It could become a kind of a tangled mess to pass around plugins so that other objects can subscribe to their events. You mentioned the
MessageQueue
class in your original post. I think you were on the right track to begin with. Maybe you need a class that provides that type of functionality for your application, but as you say theMessageQueue
class isn't exactly what you're looking for. So how about one that's designed for local communication instead? Here's my idea of what the methods for this class could look like, let's call itEventQueue
to avoid clashing with the .NET'sMessageQueue
class: Methods:void CreateEvent(string eventName);
void Subscribe(string eventName, SendOrPostCallback callback);
void Unsubscribe(string eventName, SendOrPostCallback callback);
void Send(string eventName, object state);
Ok, here's it works: The
CreateEvent
method creates an event (not in the C# sense, just in the general sense) with the specified event name. After this event is created, those objects, in this case the plugins and the system, can subscribe to the event with theSubscribe
method and unsubscribe with theUnsubscribe
method. When one object needs to send an event, it calls theSend
method, specifying the event name. It also passes along an object representing the information about that event. TheEventQueue
then looks up all of the subscribers for that event and calls theSendOrPostCallback
delegate for each subscriber, passing along the state object that was passed toSend
. The receivers of any event will need to know how to unpack thestate
object passed toSend
. This object could be null if no additional information is needed for the event, or it could represent some object that has all the details the receivers need to understand the event. Each plugin as well as the system would have access to anEventQueue
for sending and receiving events. Care would need to be taken so that s -
smesser wrote:
Thanks for the dialog as it is more helpful than you realize. You make me think about this in ways that I may overlook. It's always nice to bouce idea around.
I'm glad it's helpful. :-) It's got me thinking, too. I think the messaging you've described may be complex enough that using C# events may not be appropriate. It could become a kind of a tangled mess to pass around plugins so that other objects can subscribe to their events. You mentioned the
MessageQueue
class in your original post. I think you were on the right track to begin with. Maybe you need a class that provides that type of functionality for your application, but as you say theMessageQueue
class isn't exactly what you're looking for. So how about one that's designed for local communication instead? Here's my idea of what the methods for this class could look like, let's call itEventQueue
to avoid clashing with the .NET'sMessageQueue
class: Methods:void CreateEvent(string eventName);
void Subscribe(string eventName, SendOrPostCallback callback);
void Unsubscribe(string eventName, SendOrPostCallback callback);
void Send(string eventName, object state);
Ok, here's it works: The
CreateEvent
method creates an event (not in the C# sense, just in the general sense) with the specified event name. After this event is created, those objects, in this case the plugins and the system, can subscribe to the event with theSubscribe
method and unsubscribe with theUnsubscribe
method. When one object needs to send an event, it calls theSend
method, specifying the event name. It also passes along an object representing the information about that event. TheEventQueue
then looks up all of the subscribers for that event and calls theSendOrPostCallback
delegate for each subscriber, passing along the state object that was passed toSend
. The receivers of any event will need to know how to unpack thestate
object passed toSend
. This object could be null if no additional information is needed for the event, or it could represent some object that has all the details the receivers need to understand the event. Each plugin as well as the system would have access to anEventQueue
for sending and receiving events. Care would need to be taken so that sNow this is really getting exciting... Programming is exciting right ???? One thing is starting to get a little fuzzy for me. That is the difference betweek a message and an event. I have been kind of picturing them as one in the same. In my framework my message class derives from and IDataItem class which basically wraps key/value pairs. In my mind any message without data could be viewed as an event by it's subject.
// Event IMessage message = System.NewMessage( "music.event.endofsong"); message.Send(); // Message send from somewhere wanting to tell the music play to play a playlist. IMessage message = System.NewMessage( "music.queue.list" ); message[ "song 1"] = "song.mp3"; message{ "song 2"] = "song2.mp3"; IMessage message = System.NewMessage( "music.play" ); message.Send() // Subscribe to an event done while plugin is being loaded at app startup. System.Subscribe( "music.event.*"); // In the meantime the song get to the end so the music plugin sends IMessage message = System.NewMessage( "music.event.endofsong" ); message.Send(); By convention given my continuing example. music.play // message to tell plugin to play whats in it queue music.stop // message to tell plugin to stop playing music music.event.endoflist // message/event from plugin to subscribers notifying of end of playlist music.event.endofsong // message/event from plugin to subscribers notifying of end of a song
I like where your going with your approach. I believe that this is starting to come together.
-
Now this is really getting exciting... Programming is exciting right ???? One thing is starting to get a little fuzzy for me. That is the difference betweek a message and an event. I have been kind of picturing them as one in the same. In my framework my message class derives from and IDataItem class which basically wraps key/value pairs. In my mind any message without data could be viewed as an event by it's subject.
// Event IMessage message = System.NewMessage( "music.event.endofsong"); message.Send(); // Message send from somewhere wanting to tell the music play to play a playlist. IMessage message = System.NewMessage( "music.queue.list" ); message[ "song 1"] = "song.mp3"; message{ "song 2"] = "song2.mp3"; IMessage message = System.NewMessage( "music.play" ); message.Send() // Subscribe to an event done while plugin is being loaded at app startup. System.Subscribe( "music.event.*"); // In the meantime the song get to the end so the music plugin sends IMessage message = System.NewMessage( "music.event.endofsong" ); message.Send(); By convention given my continuing example. music.play // message to tell plugin to play whats in it queue music.stop // message to tell plugin to stop playing music music.event.endoflist // message/event from plugin to subscribers notifying of end of playlist music.event.endofsong // message/event from plugin to subscribers notifying of end of a song
I like where your going with your approach. I believe that this is starting to come together.
smesser wrote:
Now this is really getting exciting... Programming is exciting right ????
Yeah, this is fun stuff. :-D Since posting, I've already banging out most of an
EventQueue
class for fun. I'll get into the details in a moment. :)smesser wrote:
One thing is starting to get a little fuzzy for me. That is the difference betweek a message and an event. I have been kind of picturing them as one in the same.
Same here. I use event and message interchangeably. I guess if we really wanted to nail down a definition, we could say that an event is something that happens, and a message is the information that accompanies the event. But honestly, I use them both to mean the same thing. Let me run through how the
EventQueue
class can be used, and we'll see where your approach and mine can meet. First, create anEventQueue
and also create an event.EventQueue eventQueue = new EventQueue();
int endOfSongEventID = eventQueue.CreateEvent("EndOfSong");Now, subscribers can subscribe to this event. The
EventQueue
can provide a list of all of the events available on demand. Next, in some other object, we subscribe to the "EndOfSong" event.eventQueue.Subscribe("EndOfSong", new EventQueueEventHandler(HandleEndOfSong));
The second argument is a delegate to the method that will handle the "EndOfSong" event. It looks like this:
private void HandleEndOfSong(object sender, EventQueueEventArgs e)
{
// Do stuff in response to EndOfSong event.
}The
EventQueueEventArgs
class is a class representing information about any event raised by theEventQueue
. So somewhere else in our code, whereever the EndOfSong event originates, we send an event to ourEventQueue
:eventQueue.Send(endOfSongEventID, this, null);
The
endOfSongEventID
is the integer value returned when we first created the event. So instead of passing the event name when we send an event, we use the integer event ID. This is more efficient for theEventQueue
to deal with. At some point later in time, theEventQueue
dequeues the event and notifies all of the subscribers that have subscribed to that event. -
smesser wrote:
Now this is really getting exciting... Programming is exciting right ????
Yeah, this is fun stuff. :-D Since posting, I've already banging out most of an
EventQueue
class for fun. I'll get into the details in a moment. :)smesser wrote:
One thing is starting to get a little fuzzy for me. That is the difference betweek a message and an event. I have been kind of picturing them as one in the same.
Same here. I use event and message interchangeably. I guess if we really wanted to nail down a definition, we could say that an event is something that happens, and a message is the information that accompanies the event. But honestly, I use them both to mean the same thing. Let me run through how the
EventQueue
class can be used, and we'll see where your approach and mine can meet. First, create anEventQueue
and also create an event.EventQueue eventQueue = new EventQueue();
int endOfSongEventID = eventQueue.CreateEvent("EndOfSong");Now, subscribers can subscribe to this event. The
EventQueue
can provide a list of all of the events available on demand. Next, in some other object, we subscribe to the "EndOfSong" event.eventQueue.Subscribe("EndOfSong", new EventQueueEventHandler(HandleEndOfSong));
The second argument is a delegate to the method that will handle the "EndOfSong" event. It looks like this:
private void HandleEndOfSong(object sender, EventQueueEventArgs e)
{
// Do stuff in response to EndOfSong event.
}The
EventQueueEventArgs
class is a class representing information about any event raised by theEventQueue
. So somewhere else in our code, whereever the EndOfSong event originates, we send an event to ourEventQueue
:eventQueue.Send(endOfSongEventID, this, null);
The
endOfSongEventID
is the integer value returned when we first created the event. So instead of passing the event name when we send an event, we use the integer event ID. This is more efficient for theEventQueue
to deal with. At some point later in time, theEventQueue
dequeues the event and notifies all of the subscribers that have subscribed to that event.I guess the difference for me is that event seems to be some action that has happened without any state information while my version of a message can be both. That is why I want to create a message to send that would get added to the EventerrMessageQueue. Since my message inherits from a data object it can be a message, while if you create a message with only a subject then it acts as an event. I like the idea of having an event id but I see a problem with it. As you mention you could request a list of all events available. Since the list would probably return human readable strings it would make sense to have a plugin face that used strings to refer to them and an id for internal house keeping. If I requested a list of music events and the resulting list was 100, 123, 235 then you would have to maintain another list as to what they mean. And if the id aren't constant each time the app runs it could break the plugin. For example if id 5 means play. My code looks for a 5 the next time but now it's a 6. Just a thought. I think there is definitely room for two approaches here. The Callback delegate would be a good approach for most applications but for mine I think it would be better to let the System object have access to the eventqueue and the plugin manager and send out the messages via that path. Each plugin has a function called bool OnMessage( ISystem SystemObject, IMessage Message); It could return true/false if consumed or not and use the system object to create message to send the replies or responses. Just rambling a bit but this is sounding great.
-
I guess the difference for me is that event seems to be some action that has happened without any state information while my version of a message can be both. That is why I want to create a message to send that would get added to the EventerrMessageQueue. Since my message inherits from a data object it can be a message, while if you create a message with only a subject then it acts as an event. I like the idea of having an event id but I see a problem with it. As you mention you could request a list of all events available. Since the list would probably return human readable strings it would make sense to have a plugin face that used strings to refer to them and an id for internal house keeping. If I requested a list of music events and the resulting list was 100, 123, 235 then you would have to maintain another list as to what they mean. And if the id aren't constant each time the app runs it could break the plugin. For example if id 5 means play. My code looks for a 5 the next time but now it's a 6. Just a thought. I think there is definitely room for two approaches here. The Callback delegate would be a good approach for most applications but for mine I think it would be better to let the System object have access to the eventqueue and the plugin manager and send out the messages via that path. Each plugin has a function called bool OnMessage( ISystem SystemObject, IMessage Message); It could return true/false if consumed or not and use the system object to create message to send the replies or responses. Just rambling a bit but this is sounding great.
smesser wrote:
I like the idea of having an event id but I see a problem with it. As you mention you could request a list of all events available. Since the list would probably return human readable strings it would make sense to have a plugin face that used strings to refer to them and an id for internal house keeping.
I agree. The reason I was using an integer event ID is that it makes it more efficient for the
EventQueue
than having to do a string look up. However, it would be easy to use strings instead and have theEventQueue
use a hash table with the event names as keys.smesser wrote:
If I requested a list of music events and the resulting list was 100, 123, 235 then you would have to maintain another list as to what they mean. And if the id aren't constant each time the app runs it could break the plugin. For example if id 5 means play. My code looks for a 5 the next time but now it's a 6. Just a thought.
Oh, this would be easy. You could retrieve the event ID for any event as long as you know the name. Something like this:
int eventID = eventQueue["EndOfSong"];
Then once you have this event ID, you can use it to send the EndOfSong event. But you're right, using strings for event IDs would be simpler and more consistent, if less efficient for the
EventQueue
.smesser wrote:
I think there is definitely room for two approaches here. The Callback delegate would be a good approach for most applications but for mine I think it would be better to let the System object have access to the eventqueue and the plugin manager and send out the messages via that path.
The system and well as plugin manager could have access to the
EventQueue
. They could create their own events that plugins could subscribe to. However, all of this may be overkill for what you want.smesser wrote:
Each plugin has a function called bool OnMessage( ISystem SystemObject, IMessage Message); It could return true/false if consumed or not and use the system object to create message to send the replies or responses.
That sounds good. I guess the question is how to route the messages to the specific plugins? What part of this approach are you fuzzy on as to how to implement it?
-
smesser wrote:
I like the idea of having an event id but I see a problem with it. As you mention you could request a list of all events available. Since the list would probably return human readable strings it would make sense to have a plugin face that used strings to refer to them and an id for internal house keeping.
I agree. The reason I was using an integer event ID is that it makes it more efficient for the
EventQueue
than having to do a string look up. However, it would be easy to use strings instead and have theEventQueue
use a hash table with the event names as keys.smesser wrote:
If I requested a list of music events and the resulting list was 100, 123, 235 then you would have to maintain another list as to what they mean. And if the id aren't constant each time the app runs it could break the plugin. For example if id 5 means play. My code looks for a 5 the next time but now it's a 6. Just a thought.
Oh, this would be easy. You could retrieve the event ID for any event as long as you know the name. Something like this:
int eventID = eventQueue["EndOfSong"];
Then once you have this event ID, you can use it to send the EndOfSong event. But you're right, using strings for event IDs would be simpler and more consistent, if less efficient for the
EventQueue
.smesser wrote:
I think there is definitely room for two approaches here. The Callback delegate would be a good approach for most applications but for mine I think it would be better to let the System object have access to the eventqueue and the plugin manager and send out the messages via that path.
The system and well as plugin manager could have access to the
EventQueue
. They could create their own events that plugins could subscribe to. However, all of this may be overkill for what you want.smesser wrote:
Each plugin has a function called bool OnMessage( ISystem SystemObject, IMessage Message); It could return true/false if consumed or not and use the system object to create message to send the replies or responses.
That sounds good. I guess the question is how to route the messages to the specific plugins? What part of this approach are you fuzzy on as to how to implement it?
Yes, now were down to the harder part. Okay so we have an EventQueue which has a number of events in it. Since the EventQueue itself does not do the dispatching of the messages there needs to be some mechinism for seeing if there are any queued meesages and if so dispatch them. This is the fuzzy part for me. That is why I orginally had mentioned threads/timers. I would prefer not to have something polling the message queue but it may be the only way. Are you going to share your EventQueue that you have been hammering out?
-
Yes, now were down to the harder part. Okay so we have an EventQueue which has a number of events in it. Since the EventQueue itself does not do the dispatching of the messages there needs to be some mechinism for seeing if there are any queued meesages and if so dispatch them. This is the fuzzy part for me. That is why I orginally had mentioned threads/timers. I would prefer not to have something polling the message queue but it may be the only way. Are you going to share your EventQueue that you have been hammering out?
smesser wrote:
Okay so we have an EventQueue which has a number of events in it. Since the EventQueue itself does not do the dispatching of the messages there needs to be some mechinism for seeing if there are any queued meesages and if so dispatch them.
Oh, but the
EventQueue
does take care of that for us. :) It runs in its own thread. Actually, it uses myDelegateQueue
class, which runs in its own thread. The dispatching of the events is taken care of by theEventQueue
. Without that functionality, it wouldn't be of much use to us.smesser wrote:
Are you going to share your EventQueue that you have been hammering out?
Yes. I'll try to post a link to where you can download it within the hour or so. It will be an untested version, but at least you'll get to play around with the class to see if it's what you're looking for.
-
smesser wrote:
Okay so we have an EventQueue which has a number of events in it. Since the EventQueue itself does not do the dispatching of the messages there needs to be some mechinism for seeing if there are any queued meesages and if so dispatch them.
Oh, but the
EventQueue
does take care of that for us. :) It runs in its own thread. Actually, it uses myDelegateQueue
class, which runs in its own thread. The dispatching of the events is taken care of by theEventQueue
. Without that functionality, it wouldn't be of much use to us.smesser wrote:
Are you going to share your EventQueue that you have been hammering out?
Yes. I'll try to post a link to where you can download it within the hour or so. It will be an untested version, but at least you'll get to play around with the class to see if it's what you're looking for.
Cool on both parts. The EventQueue runing on it's own thread and the download I look forward to it.
-
Cool on both parts. The EventQueue runing on it's own thread and the download I look forward to it.
Here[^] is the download for the
EventQueue
class. In addition, you'll need to download the source code for my DelegateQueue[^] class. And the code for my Deque[^] class. You can compile all of this together into one assembly, though you'll want to change the namespace names so that they all match, and maybe move the using LSCollections directive. An alternative would be to use the assemblies that I have compiled. I can email you those if you'd like. Let me know how it goes and if you have any questions. Again, theEventQueue
class is completely untested. -
Here[^] is the download for the
EventQueue
class. In addition, you'll need to download the source code for my DelegateQueue[^] class. And the code for my Deque[^] class. You can compile all of this together into one assembly, though you'll want to change the namespace names so that they all match, and maybe move the using LSCollections directive. An alternative would be to use the assemblies that I have compiled. I can email you those if you'd like. Let me know how it goes and if you have any questions. Again, theEventQueue
class is completely untested.Thanks, I have downloaded your code and put all of the required files into one project so that I would at least build. It will take some time for all this to sink in and for me to understand the code. I don't understand invoke as I have not used it yet. At a quick glance I don't understand how the EventQueue is running in a thread but I only have 10 minutes vested thus far. Are you just banging this out for me or will you have an example to use the EventQueue class? Thanks much for your efforts and discussion.
-
Thanks, I have downloaded your code and put all of the required files into one project so that I would at least build. It will take some time for all this to sink in and for me to understand the code. I don't understand invoke as I have not used it yet. At a quick glance I don't understand how the EventQueue is running in a thread but I only have 10 minutes vested thus far. Are you just banging this out for me or will you have an example to use the EventQueue class? Thanks much for your efforts and discussion.
smesser wrote:
Are you just banging this out for me or will you have an example to use the EventQueue class?
I may devote an article to it at some point. I'll definitely put it in the next version of my state machine toolkit for others to use. Let's see if I can give you a quick example of using the
EventQueue
.public class MySystem
{
private EventQueue eventQueue = new EventQueue();private MusicPlugin musicPlugin; public MySystem() { // Create events. eventQueue.CreateEvent("Play"); eventQueue.CreateEvent("PlayingStopped"); // Create music plugin and give it the event queue. musicPlugin = new MusicPlugin(eventQueue); // Subscribe to the playing stop event. eventQueue.Subscribe("PlayingStopped", new EventQueueEventHandler(HandlePlayingStopped); } private void HandlePlayingStopped(object sender, EventQueueEventArgs e) { // Logic for handling playing stopped event. }
}
Here, the system object handles an event sent to it from the music plugin telling the system that it has stopped playing. Also, the system takes on the responsibility for creating all of the events before passing the event queue on to the plugin(s).
public class MusicPlugin
{
private EventQueue eventQueue;public MusicPlugin(EventQueue eventQueue) { this.eventQueue = eventQueue; eventQueue.Subscribe("Play", new EventQueueEventHandler(HandlePlayEvent)); } private void HandlePlayEvent(object sender, EventQueueEventArgs e) { // Logic for starting playback. } public void StopPlaying() { eventQueue.Send("PlayingStopped", this, null); }
}
Now with an example this small, there's not much of an advantage here over using C#'s built in events. However, if you have a lot of plugins that are sending events to each other as well as to the system, this approach could help keep the plugins decoupled. You would have one central event queue for handling all of the event notification.