event priority and process order - c#

Is there a way to specify an order or priority to handle registered event delegates? For example, I have an event that I would like processed immediately before any other events, but I want other objects to be allowed to register listeners to the event as well. How can this be accomplished?
Lets say I want proc1 to always run before proc 2.
class MessageProcessor
{
private DataClient Client;
public MessageProcesser(DataClient dc)
{
Client = dc;
Client.MessageReceived += ProcessMessage;
}
void proc1(MessageEventArgs e)
{
// Process Message
}
}
class DataClient
{
public event MessageReceievedHandler MessageReceived;
}
void main()
{
DataClient dc = new DataClient();
MessageProcessor syncProcessor = new MessageProcessor(dc); // This one is high priority and needs to process all sync immediately when they arrive before any data messages
MessageProcessor dataProcessor= new MessageProcessor(dc); // This one can process the data as it has time when sync messages are not being processed.
// do other stuff
}
The reason for doing this, I have a server that is sending messages over a UDP stream. It will send sync messages before a burst of data. I realize both handlers will fire when a sync message is received, but to decrease latency I would like the syncProcessor objects events processed before the dataProcessor events. This would decrease the latency of the Sync Message being processed.
In addition, someone else on my team may want to register events to process specific messages also. They may have their own object that will register an event (May not be MessageProcessor), even still the Sync message should have as low latency as possible.
EDIT Made the objective more clear with a better example.

When you subscribe to an event multiple times, there is no possible way to be sure of the execution order of your handlers when the event is fired.
According to this answer, the order in the subscription order, but as the post author said, it's an implementation detail and you must not rely on it.
You could of course write your own "event manager" (see dirty example below) that executes your handlers in a known order, but I don't think it would be a good idea. Maybe you should re-design your event to remove your requirement.
public class MyClass
{
// Could be anything...
public delegate void MyEventHandler(object sender, EventArgs e);
public event MyEventHandler TestEvent;
public void Test()
{
if (this.TestEvent != null)
{
this.TestEvent(this, EventArgs.Empty);
}
}
}
public class EventManager
{
private List<EventHandler> Handlers = new List<EventHandler>();
public void AddHandler(EventHandler handler)
{
this.Handlers.Add(handler);
}
public void RemoveHandler(EventHandler handler)
{
this.Handlers.Remove(handler);
}
public void Handler(object sender, EventArgs e)
{
foreach (var z in this.Handlers)
{
z.Invoke(sender, e);
}
}
}
private static void Main(string[] args)
{
MyClass test = new MyClass();
EventManager eventManager = new EventManager();
// Subscribes to the event
test.TestEvent += eventManager.Handler;
// Adds two handlers in a known order
eventManager.AddHandler(Handler1);
eventManager.AddHandler(Handler2);
test.Test();
Console.ReadKey();
}
private static void Handler1(object sender, EventArgs e)
{
Console.WriteLine("1");
}
private static void Handler2(object sender, EventArgs e)
{
Console.WriteLine("2");
}

In this case, you are better off simply calling the second event at the end of the first event, etc.

If this is your own event that you defined, then your best bet might be to extend it to have a BeforeMessageReceived, MessageReceived and AfterMessageReceived events. (okay, so maybe MessageProcessed would be a better root, since you can know before a message is received).
This will give you more control over exactly where different event handlers occur.
You see the same before, event, after patten all over the place.

Im going to go out on a limb and say no. AFAIK events are dispatched ASYNCHRONOUSLY by nature. So that will be dispatched in the order they are bound. however the results may return in a different order. The only way would be to dispatch your 2nd event inside the callback for the first event. This is not language specific, just more on the architecture of events.
In your example since the calls are void y not run proc2 at the end of proc1?

Related

Will several bindings of static/global Event handler to Events in a class, lead to a thread/memory leak?

I have a class with EventHandler bindings at the constructor, that will be instantiated thousand times within application lifecycle. The question is: Will this approach leads to memory/thread leaks?
I did this way (code below), because I need to be notified every time SomeMethod() runs, whatever instance run it. Foo class (the publisher) will be short-lived, however the handlers will live until the application closes.
I ask this because, when working with Windows Forms, each form can hold several event handlers/delegates and everything is fine because all those delegates are inside the form and will be disposed when the form closes. But how about static event handlers/delegates, that could be even on separate projects?
Will I need to write a destructor to detach those event handlers?
Should I go with Weak Event Pattern?
Restriction: I must do this with .NET 3.5. I know I could do this with TPL, setting a "Fire and Forget" Task.
Thank you in advance.
Code:
public class Foo
{
public event EventHandler SomeEvent;
public Foo()
{
SomeEvent += FooHandlers.Foo_SomeEvent1;
SomeEvent += FooHandlers.Foo_SomeEvent2;
}
public void RaiseEvents(EventHandler evt, EventArgs args)
{
var eventObj = evt;
var listeners = eventObj.GetInvocationList();
foreach (var listener in listeners)
{
var method = (EventHandler)listener;
ThreadPool.QueueUserWorkItem(callBack => method(this, args));
// Handlers will do a lot of things, so I don't want
// them blocking the Main thread
}
}
public void SomeMethod()
{
// do something here
RaiseEvents(SomeEvent, new EventArgs());
}
}
public static class FooHandlers
{
public static void Foo_SomeEvent1(object sender, EventArgs e)
{
//do something here
}
public static void Foo_SomeEvent2(object sender, EventArgs e)
{
//do something different here
}
}
Since your handlers are static methods the delegate you're adding to the event doesn't have an object instance, so there is no object instance being kept alive for the duration of the object with the event.
And even if you did use an object instance to attach the handler, it wouldn't be a problem, because the object with the event is short lived. The only time there is a problem is when the object with the event is long lived, and the object that has a handler to itself assigned is short lived, and consumes a lot of resources to keep alive.

Event handler not firing on class method

I have an event handler in a class which doesnt seem to trigger. I wonder if anyone had any ideas on why this may be happening (or not happening as is the case).
The class inherits from another class and basically listens for messages from a message queue. When a message hits the queue the method onMessage() is called.
From my (winforms, c#, .net 3.5) UI form, I'm trying to get the received message(s) back to the UI.
If I call the method onMessage() manually from the instance on my form, the eventhandler does trigger correctly and passMessage is executed on my UI form.
But when I receive a message thats come automated from the queue I'm listening on, the event handler is not triggered. I dont ever call the onMessage() method, that happens automatically.
Does anyone have any ideas why the event handler is not triggering when onMessage() is called everytime I receive a message?
Thanks
UI:
private void btnConnect(object sender, EventArgs e)
{
MessageQueue myMQ = new MessageQueue();
myMQ.Connect(...);
//Register handler
myMQ.MsgTrigger += new EventHandler(passMessage);
}
public void passMessage(object s, EventArgs e)
{
Console.WriteLine(s.ToString()); //Not sure if this is a good way to pass back a value
}
Class:
namespace MQListener
{
class MessageQueue : MQ.MessageListener
{
public event EventHandler MsgTrigger;
public virtual void onMessage(MQ.Message Message)
{
MQ.TextMessage txtMessage = (MQ.TextMessage)Message;
String MsgBody = txtMessage.getMessage();
Console.WriteLine(MsgBody);
object objMsg = (object)MsgBody;
var _Trigger = MsgTrigger;
if(_Trigger != null)
_Trigger(objMsg, null);
}
}
}
Your event subscription should happen before you connect:
private void btnConnect(object sender, EventArgs e)
{
MessageQueue myMQ = new MessageQueue();
//Register handler
myMQ.MsgTrigger += new EventHandler(passMessage);
myMQ.Connect(...);
}
You can only update controls from the UI thread, so to prevent the error "'txtMessage' accessed from a thread other than the thread it was created on.", you need to check the control's InvokeRequired property. If true, you need to call the Invoke() method. See this SO question: Automating the InvokeRequired code pattern

Getting a class to 'inform' another class that it needs to change (Events?)

Okay, I've been searching on the site and Google and can't quite get my head around where things need to be in terms of delegates and eventhandlers and the like so hopefully someone here can help/explain what I need to do.
So, I am writing a simple database application (using SQLite). There is a mainform that is the MDI parent (that's basically a big window with menus at the top). The menus launch other windows that allow view, edit and insert into various tables of the database.
One of those windows is a LOG window which shows my log table.
At the moment, if a user changes something in the window showing the data in TABLE. The operation also writes into the log table. If the Log window is open, however, the log view doesn't update.
So, I've figured out I probably need to 'fire' an event from my TABLE UPDATE code that my LOG window 'subscribes' to (so it can update the DataGridView).
What I can't figure out is where the different 'bits' of the event go.
Should the MdiParent have the public delegate void EventHandler();? If not where?
which class gets the public static event EventHandler logGoneStale;?
The only bit I'm reasonably sure about is that the Window that displays the log (which has a method called public void UpdateLogDataGridView() - which calls the database object/methods to (re-)populate the datagridview) needs to have:
something like logGoneStale += new EventHandler(UpdateLogDataGridView); in it. Is that at least right?
Totally befuddled - it seems none of the event examples/tutorials on MSDN are trying to do what I want to achieve.
You need to define an event in the class that is sending the event, and append an event handler in the class that should receive the event. To make things slightly easier, starting with C# 3.5 you can forget about the delegate keyword altogether and use a lamba expression as event handler. Also note that it in most cases it makes no sense to make an event static, since usually events are fired by an instance, not by a class.
Example:
class SendsEvent
{
public event EventHandler MyEvent;
public void FireEvent()
{
if(MyEvent != null) // MyEvent is null if no handlers have been attached
{
MyEvent(this, new EventArgs()); // event fired here
}
}
}
class ReceivesEvent
{
private SendsEvent eventSource;
public ReceivesEvent(SendsEvent eventSource)
{
this.eventSource = eventSource;
// Attach event handler - can be a lambda expression
// or method with signature
// "void HandleEvent(object sender, EventArgs e)"
this.eventSource.MyEvent += (sender, args) =>
{
// do something when event was fired
Console.Out.WriteLine("Hello. Event was fired.");
};
}
}
class Program
{
public static void Main()
{
var eventSource = new SendsEvent();
var eventReceiver = new ReceivesEvent(eventSource);
eventSource.FireEvent();
}
}
I hope this helps you.
Working with events requires you to have both an event publisher and an event subscriber.
#chris' answer is correct.
Besides, you need to raise the event on the closest point where the action for which you want to be notified takes place.
For example, implementing the INotifyPropertyChanged interface.
public class Customer : INotifyPropertyChanged {
public string Name { get; set; }
public string Address {
get { return address; }
set {
address = value;
if (thereArePropertyChangedEventSubcribers())
raisePropertyChangedEventFor("Address");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void raisePropertyChangedEventFor(string propertyName) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private bool thereArePropertyChangedEventSubcribers() {
return PropertyChanged != null;
}
private string address;
}
So here, the Customer class allows for the publishment of its change of address. So, whenever anyone is interested to be notified when the address has changed, it subscribes to the event like so:
Customer.PropertyChanged += new PropertyChangedEventHandler(customerPropertyChanged);
Or else like so:
Customer.PropertyChanged += customerPropertyChanged;
You might even have noticed that the closest point where the address has changed in directly after it has actually changed. The only requirement is that the method used as the event handler has the same signature as the event itself. If you take a look at the PropertyChangedEventHandler Delegate, one may notice that it signature awaits an object as the first parameter, that is, the object that fired the event, and a PropertyChangedEventArgs instance to notify about the property that has changed.
To come back to your example, you wish to be noticed whenever a log has been inserted into the underlying database so that a refresh of your Log window may occur. There are two questions that need to be answered whenever you want to use events.
What shall my publisher be?
What shall my subscriber be?
What shall my publisher be?
Should the MdiParent have the public delegate void EventHandler();?
Short answer: No!
If not where?
The event declaration best fits the publisher. Should you have a class responsible for logging, then this is where the public delegate void EventHandler(); should reside, as it is it that is responsible to raise the event whenever there are subscribers.
Whenever there is a successful Log inserted, it shall notify whatever subscriber interested to know about the new Log Entry.
public class Log {
public void UpdateLog(string description) {
// insert the new Log line into your database.
if (thereIsAtLeastOneNewLogEntryAddedSubscriber())
raiseTheNewLogEntryAddedEvent();
}
public event EventHandler NewLogEntryAdded;
private raiseTheNewLogEntryAddedEvent() {
NewLogEntryAdded(this, EventArgs.Empty);
}
private bool thereIsAtLeastOneNewLogEntryAddedSubscriber() {
return NewLogEntryAdded != null;
}
}
What shall my subscriber be?
This question can be answered through another question:
What do you need to do when the event fires?
In your case, you wish to update a Log window whenever it is opened.
The only bit I'm reasonably sure about is that the Window that displays the log (which has a method called public void UpdateLogDataGridView() - which calls the database object/methods to (re-)populate the datagridview) needs to have:
something like logGoneStale += new EventHandler(UpdateLogDataGridView); in it. Is that at least right?
Yes, you're right! =D
You actually subscribe to the event per this line. So, it tells the application that the window that displays the log is interested to know about log changes in your database.
public class WindowThatDisplaysTheLog : Form {
public WindowThatDisplaysTheLog() {
InitializeComponent();
log = new Log();
log.NewLogEntryAdded += UpdateLogDataGridView;
}
private void UpdateLogDataGridView(object sender, EventArgs e) {
// Reload your Log entries from the underlying database.
// You now shall see the LogDataGridView updating itself
// whenever a new log entry is inserted.
}
private Log log;
}

Custom Event handler is getting called twice?

I've created an event handler that simply returns a list of objects that I receive from a web service when the call completes.
Now I went ahead and ran the app in debug mode and found out that the first time the event is called it works perfectly, but immediately after it completes the event is being fired for a second time. I've checked and am absolutely sure I am not calling the event more than once in the receiver class.
This is my first shot at creating custom event handlers inside my applications so I am not entirely sure the implementation is 100% accurate.
Any ideas of what might be causing this? Is the way I created the event handler accurate?
This is the DataHelper class
public class DataHelper
{
public delegate void DataCalledEventHandler(object sender, List<DataItem> dateItemList);
public event DataCalledEventHandler DataCalled;
public DataHelper()
{
}
public void CallData()
{
List<DataItem> dataItems = new List<DataItem>();
//SOME CODE THAT RETURNS DATA
DataCalled(this, dataItems);
}
}
This is where I subscribed to my event:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
GetNewDataItems();
}
private void GetNewDataItems()
{
try
{
DataHelper dataHelper = new DataHelper();
dataHelper.CallData();
dataHelper.DataCalled += new DataHelper.DataCalledEventHandler(dataHelper_DataCalled);
}
catch
{
//Handle any errors
}
}
}
void dataHelper_DataCalled(object sender, List<DataItem> dataItemsList)
{
//Do something with results
//NOTE: THIS IS WHERE THE EXCEPTION OCCURS WHEN EVENT IS FIRED FOR SECOND TIME
}
Probably you added the delegate twice, is it possible?
In this case the problem is not in who calls the delegate but in who adds the delegate to the event.
Probably you did something like...
private Class1 instance1;
void callback(...)
{
}
void myfunction()
{
this.instance1.DataCalled += this.callback;
this.instance1.DataCalled += this.callback;
}
If not, try to add a breakpoint where you subscribe to the event and see if it is called twice.
As a side note, you should always check for null when calling an event, if there is no subscriber you can get a NullReferenceException.
I would also suggest you to use a variable to store the event delegate to avoid the risk of multithreading failure.
public void CallData()
{
List<DataItem> dataItems = new List<DataItem>();
var handler = this.DataCalled;
if (handler != null)
handler(this, dataItems);
}
Edit: since now I see the code, is obvious that each time you call the GetNewDataItems method you are subsribing every time to the event.
Do in such a way you subscribe only once, for example, in constructor, or store your variable somewhere or deregister the event when you finish.
This code contains also a probable memory leak: every time you add a delegate you keep alive both the instance that contains the event and the instance that contains the subscribed method, at least, until both are unreferenced.
You can try to do something like this...
void dataHelper_DataCalled(object sender, List<DataItem> dataItemsList)
{
// Deregister the event...
(sender as Class1).DataCalled -= dataHelper_DataCalled;
//Do something with results
}
In this way however you must ensure that if there is not an exception during the event registration the event will be fired or you have again memory leaks.
Instead of an event perhaps you need just a delegate. Of course you should set your delegate field to null when you want to release the delegate.
// in data helper class
private DataHelper.DataCalledEventHandler myFunctor;
public void CallData(DataHelper.DataCalledEventHandler functor)
{
this.myFunctor = functor;
//SOME CODE THAT RETURNS DATA
}
// when the call completes, asynchronously...
private void WhenTheCallCompletes()
{
var functor = this.myFunctor;
if (functor != null)
{
this.myFunctor = null;
List<DataItem> dataItems = new List<DataItem>();
functor(this, dataItems);
}
}
    
// in your function
...    dataHelper.CallData(this.dataHelper_DataCalled);    ...
The below lines on your code should be flipped. That is
These lines
dataHelper.CallData();
dataHelper.DataCalled += new DataHelper.DataCalledEventHandler(dataHelper_DataCalled);
Should be:
dataHelper.DataCalled += new DataHelper.DataCalledEventHandler(dataHelper_DataCalled);
dataHelper.CallData();
Because you first need to attach the event handler and then call other methods on the object which can raise the event

Are there pitfalls to using static class/event as an application message bus

I have a static generic class that helps me move events around with very little overhead:
public static class MessageBus<T> where T : EventArgs
{
public static event EventHandler<T> MessageReceived;
public static void SendMessage(object sender, T message)
{
if (MessageReceived != null)
MessageReceived(sender, message);
}
}
To create a system-wide message bus, I simply need to define an EventArgs class to pass around any arbitrary bits of information:
class MyEventArgs : EventArgs
{
public string Message { get; set; }
}
Anywhere I'm interested in this event, I just wire up a handler:
MessageBus<MyEventArgs>.MessageReceived += (s,e) => DoSomething();
Likewise, triggering the event is just as easy:
MessageBus<MyEventArgs>.SendMessage(this, new MyEventArgs() {Message="hi mom"});
Using MessageBus and a custom EventArgs class lets me have an application wide message sink for a specific type of message. This comes in handy when you have several forms that, for example, display customer information and maybe a couple forms that update that information. None of the forms know about each other and none of them need to be wired to a static "super class".
I have a couple questions:
fxCop complains about using static methods with generics, but this is exactly what I'm after here. I want there to be exactly one MessageBus for each type of message handled. Using a static with a generic saves me from writing all the code that would maintain the list of MessageBus objects.
Are the listening objects being kept "alive" via the MessageReceived event?
For instance, perhaps I have this code in a Form.Load event:
MessageBus<CustomerChangedEventArgs>.MessageReceived += (s,e) => DoReload();
When the Form is Closed, is the Form being retained in memory because MessageReceived has a reference to its DoReload method? Should I be removing the reference when the form closes:
MessageBus<CustomerChangedEventArgs>.MessageReceived -= (s,e) => DoReload();
Well, yes, you should, but if you use the lambda syntax as you've done in your example I think it won't work (by which I mean, the handler will not be de-registered successfully).
Someone correct me if I'm wrong, but I believe this is true because using the lambda syntax effectively creates a new EventHandler<CustomerChangedEventArgs> object, with its own place in memory. When you try to remove this handler, using the lambda syntax again, this creates yet another new EventHandler<CustomerChangedEventArgs> object, which is not equal to the first one you created; and so the first one never gets de-registered.
Sadly, I think you'll need to actually define a method like this:
DoReload(object sender, CustomerChangedEventArgs e) {
DoReload(); // your original overload, which doesn't actually care
// about the sender and e parameters
}
This way you can do:
MessageBus<CustomerChangedEventArgs>.MessageReceived += DoReload;
And later:
MessageBus<CustomerChangedEventArgs>.MessageReceived -= DoReload;
Yes, there are problems. Your event handlers will cause the form object to stay referenced, you have to explicitly unregister the event handlers. The lambdas make this impossible, you'll have to write an explicit handler.
This pattern has a name, "Event Broker service". It is part of the Composite UI Application Block, published by Microsoft's Pattern and Practices team. Beg, borrow and steal (if not use) what you can from this.
You could use weak references to store the event handlers. That way, unhooked handlers won't prevent garbage collection of the objects.
public static class MessageBus<T> where T : EventArgs
{
private static List<WeakReference> _handlers = new List<WeakReference>();
public static event EventHandler<T> MessageReceived
{
add
{
_handlers.Add(new WeakReference(value));
}
remove
{
// also remove "dead" (garbage collected) handlers
_handlers.RemoveAll(wh => !wh.IsAlive || wh.Target.Equals(value));
}
}
public static void SendMessage(object sender, T message)
{
foreach(var weakHandler in _handlers)
{
if (weakHandler.IsAlive)
{
var handler = weakHandler.Target as EventHandler<T>;
handler(sender, message);
}
}
}
}

Categories