   [.net] Raising Events in .NET vs Polling a Queue
  I guess this is a really general question, and has to do with the network layer of the MMORPG we're working on.There are two ways I was considering handling Messages as the came into the server.  (After being assembled by the packet assembler)First, was raising an event.  As soon as a command was assembled, an event would get raised, and go off and process.  However, this seems like it could backfire, and open up multiple threads at the same time, lagging the system.Second was polling a Queue of Messages.  When a message is received, dump it into a pool (FIFO), to get processed.  As soon as its processed, wipe it from the pool.  This also has its drawbacks, as there is a slight delay, while the timer repolls, for messages to get processed.  Also, there is a chance, that if you don't disabled the timer, that it'll try to process the command a second time, or third, or fourth...Any ideas on which is gonna scale better, or which is going to be more efficient in the long run?   
  I don't understand -- where do the extra threads come from when you raise an event? Surely you don't actually create a new thread for each event you handle?Also, I don't see why you would have any risk of processing the same received message more than once -- typically, you dequeue a message from the queue, and then handle it. Because it's no longer in the queue, how could it be processed more than once?Regarding the timing delay, there really is not much difference. In the FIFO case, you will have slightly more possible buffering under heavy load (packet bursts), so it might be more robust. On the other hand, if you get more packets than you can handle (overload), then the first method will drop the packets earlier, and thus avoid a server meltdown because of running out of memory in a wildly growing FIFO. Thus, if you use the FIFO, you should probably make sure it has a fixed upper size, and just drop packets that attempt to fill beyond that.   ;Quote:Original post by hplus0603I don't understand -- where do the extra threads come from when you raise an event? Surely you don't actually create a new thread for each event you handle?I guess my thoughts on event handling are a bit...shortsighted?  I was under the impression in .NET that if you raised an event twice, and the first one hadn't completed, that it was going to spawn a new copy of the delegate and run side by side.  Does it handle it in a FIFO fashion too?Quote:Also, I don't see why you would have any risk of processing the same received message more than once -- typically, you dequeue a message from the queue, and then handle it. Because it's no longer in the queue, how could it be processed more than once?Good point.  I put the remove command ahead of processing, so it won't read twice.Quote:Regarding the timing delay, there really is not much difference. In the FIFO case, you will have slightly more possible buffering under heavy load (packet bursts), so it might be more robust. On the other hand, if you get more packets than you can handle (overload), then the first method will drop the packets earlier, and thus avoid a server meltdown because of running out of memory in a wildly growing FIFO. Thus, if you use the FIFO, you should probably make sure it has a fixed upper size, and just drop packets that attempt to fill beyond that.Well, at that point though, they're not Packets.  They're fully assembled messages.  Once a message has been assembled, all related packets, or parts of it, are wiped from the incoming PacketQueue.  I'd have to then check if a message is "important" right?;Quote:Original post by SiberwulfI guess my thoughts on event handling are a bit...shortsighted?  I was under the impression in .NET that if you raised an event twice, and the first one hadn't completed, that it was going to spawn a new copy of the delegate and run side by side.  Does it handle it in a FIFO fashion too?That's something I really don't know if there's a 100% reliable answer to.  Events and multithreading can drive a coder crazy if you think too hard about it.  If you run into documentation that says one way or the other (launching threads or sequential), be sure to let us know!   ;  .NET Events are just function calls with a little bit of glue on them; pretty much like a delegate. You can't even "raise" a second event until the first one returns (unless you raise it from another thread -- at which point it will be dispatched in that thread). For further information, see the "Events and Delegates" section of the .NET Framework Developer's Guide.Meanwhile, to confuse the word "event," there's also the Win32 "HEVENT" kind of event, which is a synchronization primitive. It will not, in itself, cause anything special to happen, but threads may use the semantics of the HEVENT to synchronize their behavior.Btw: this seems to be a C# question, rather than a networking question :-) Thus, I'm moving it to the .NET forum.   ;  One of the approaches you could try is making your event a non-multicast event. That means that only one handler can be set for it. That's basically the same approach as your FIFO pool. It looks like the event in the pool is being processed only once - as its being taken off the pool. And it sounds like you don't want every thread working off the event. So, create the event non-multicast and create a class that registers for that event and you might get what you're looking for.I haven't done single-cast events before but I definitely know that you can do it. You'll have to google or code project it to find the technique - but I know its possible.Hope this helps!   ;Quote:Original post by caledhI haven't done single-cast events before but I definitely know that you can do it. You'll have to google or code project it to find the technique - but I know its possible.I know if you make the delegate non-void (returns something) then the C# compiler will make it singlecast. I assume an out parameter would also work, and maybe a ref parameter?   ;  I think what you're asking are actually two separate questions, and the answer to both depends on how you are designing your network engine.The first question is, "Do I want my messages to be handled at the time of arrival or to be queued for later handling, say at a specific point in the main loop?"  If the answer is the ladder, you're going to have to use a message queue of some sort regardless of how you eventually decide to process your messages.The second question is, "Do I want my messages to all be handled by a central monolothic code point, or in a distributed manner where any class that desires can request notification of network messages?"  The ladder option here is the one for which you would want to implement an event system.  Note that even if you use events in this manner you still might decide to queue your messages and fire all the events at a specific point as indicated in the previous paragraph.  An important consideration at this point is that events in .NET are generally unreliable if you require a specific order of processing.  Say, for example, if your physics simulation needs to be updated before your graphics or whatnot, events are probably NOT the best option.  While I believe that event delegates are triggered in the order of registration in .NET (although I'm not entirely sure, you'd have to look it up or ask someone else), the event handling mechanism provided by the .NET framework is not optimal in an environment where order is important, as it provides no way to designate priority to delegates (unlike, say, the signal/sink system provided by the boost C++ library).  Of course, your could try to require a specific order of registration for event handlers, but I don't think this is very a good coding practice.Generally, my suggestion would be to handle the actual processing of your network messages in a centralized manner, and allow your game objects themselves to provide any needed event type notification.  For example, the network code would directly update, say, an enemy's world position, and then the object encapsulating that enemy would fire off an event indicating that its position has been updated.  Of course, this may not be ideal depending on how your engine is designed.  Hope this helped.   ;Quote:Original post by ShinkageGenerally, my suggestion would be to handle the actual processing of your network messages in a centralized manner, and allow your game objects themselves to provide any needed event type notification.  For example, the network code would directly update, say, an enemy's world position, and then the object encapsulating that enemy would fire off an event indicating that its position has been updated.  Of course, this may not be ideal depending on how your engine is designed.  Hope this helped.Great read!  Very helpful indeed!  However, this last paragraph really touched on the question I was raising.  My scenario really is when there are "message bursts", such as 40 players fighting a boss mob, all doing something, at the same time, in a very close vicinity of each other. (All would see each other working).My question, is how do I accomidate this flurry of activity.  If I have 100 messages come into the Server at once, and I go into something like an arraylist of those messages, is message at offset 99 technically as valid as the message at offset 0?If, on the other hand, I raise an event, and those events are all executing at the same time, I've just created 100 copies of the event handler at the same time.  This would seem pretty intense, especially if sustained over a long period of time (such as a constantly busy captial city).  However, if there is an psuedo-lock on the event handler until its completed, I don't know that raising events really gives a benefit over polling the Queue.Seems I ended myself back up right where I began (but with a little more knowledge, at least)...:);  I think you're making events into being a lot more than they actually are.  Essentially, all that events boil down to are storage areas for delegates (function pointers, links to functions in simplest terms) with convenient naming and access schemes.  When you raise an event all you're effectively doing is to call all the individual functions you've registered with that event.  This calling is NOT done asynchronously.  The functions are just called sequentially, one after another, and control doesn't return to the call point until after all the delegate functions have returned.The real benefit of events is the design pattern they enable.  Instead of having the function caller have to be aware of what functions need to be called, events allow the actual callees to register themselves for certain notifications.  It promotes good OO programming practices of encapsulation--you don't want classes having to know too much about how eachother actually work.  When you use events all the function caller has to know is "such and such event has occurred," and it does NOT need to know which other classes care.To answer your question simply, it doesn't seem like events are what you want to use.  Let's say you have all 40 player objects registered to receive network message events.  That means that every time one of those events is raised, every one of those 40 objects will process it, whether they need it or not.  I think a better design would be to make the actual objects available to a message processing function, and have that function parse all the network messages that are received and dispatch it to the appropriate objects.The problem here is that I can tell you what I think you should do, but that doesn't really help you understand the reasoning and design considerations behind my choices.  Hopefully my explanation up top has made it more clear why I'd do things a certain way.   