I have some confusion regarding Events. What are the basic differences between C# Events and Methods?
A method is simply code contained within a class to implement a piece of functionality. All code in C# is contained within methods.
As for events, well, suppose you had a simple class which implemented a counter (lets call it the Counter object). Now suppose you wanted to let other objects unrelated to Counter know when the count reached 100. How would you do it?
A logical way would be to allow the other objects to specify one of their own methods they want to be called when the count reaches 100. Each object could then, individually, tell the Counter object which method they want to be called. The Counter object saves this list of methods and, when the count reaches 100, calls each of the saved methods in turn.
This is the how Events work - the Counter class contains an event member (called say, CounterIs100) which other object instances link one of their own methods to. When the Counter object detects that it has has reached 100, it invokes the CounterIs100 member which, automatically, calls all the methods currently linked to it, thus notifying each object in turn that the count has indeed reached 100.
If no objects have linked a method to the CounterIs100 event member, it will be null, so there is no need for the Counter object to invoke the event member.
class Counter
{
// this is the count field used to save the current count value
private int count;
// this is the event member which holds all the methods other objects have specified
public event CounterIs100Delegate CounterIs100;
// This is a method. It invokes the CounterIs100 event member if anyone has subscribed to it
protected void OnCounterIs100()
{
// see if anyone has subscribed (linked) their method to this event
if (CounterIs100 != null)
{
// invoke the event - this will call all subscribed methods
CounterIs100();
}
}
// This is a method. It increments the counter variable stored by this object
public void Increment()
{
count++;
// if the count is 100, invoke the event
if (count == 100)
OnCounterIs100();
}
}
// This is a delegate. It is used to define a template for other objects wishing to
// subscribe to the CounterIs100 event. The methods other objects link to the
// CounterIs100 event must match this declaration (although the name can be changed)
public delegate void CounterIs100Delegate();
// This is a class, unrelated to Counter, but uses its events
class SiteHits
{
Counter hitCounter = new Counter();
public SiteHits()
{
// We want to know when the number of site hits reaches 100.
// We could monitor this ourselves, but we know the Counter class already
// does this, so we just link our method to its event
hitCounter.CounterIs100 += this.WhenSiteHitsReaches100;
}
public void PageRequested()
{
// someone has requested a page - increment the hit counter
Console.WriteLine("We've been hit!");
hitCounter.Increment();
}
// this is the method we want called when the CounterIs100 event occurs.
// note that the return value and parameters match CounterIs100Delegate above.
public void WhenSiteHitsReaches100()
{
Console.WriteLine("Woohoo! We've reached 100 hits!");
}
}
C# Events are a specific form of delegates. If you have programmed in other languages, like C++, you could compare a delegate to a function ("method") pointer - it points to some code in memory. When you call the pointer as a method, you actually call the method at the address the pointer points to.
This is necessary to provide decoupling between the caller and the callee - so you don't have to have all methods ready when you publish code that calls them (which, wouldn't be possible - the Forms controls developers can't possibly know the code that needs to be called when a Button is pressed). You call the pointer, and the other developer sets it to an appropriate memory address later.
P.S. delegates and Events however, have other advantages over plain function pointers - you can be sure that it will point to a good-looking method, taking the correct number and type of arguments and returning the correct type.
An event in C# is a way for a class to provide notifications to clients of that class when some interesting thing happens to an object.
http://msdn.microsoft.com/en-us/library/aa645739%28v=vs.71%29.aspx
A method is a code block containing a series of statements. In C#, every executed instruction is done so in the context of a method.
http://msdn.microsoft.com/en-us/library/ms173114%28v=vs.80%29.aspx
An event in .net is a pair of methods, one for "Add" and one for "Remove", each of which accepts a delegate. Typically, the "Add" method will take the passed-in delegate and add it to either a list of delegates or a MulticastDelegate; passing a delegate to the "Remove" event which was previously passed to the "Add" method should remove that delegate from the list. If one doesn't request otherwise, both C# and vb.net will by default automatically create "Add" and "Remove" events which will behave as indicated above.
This is from MSDN:
An event in C# is a way for a class to provide notifications to clients of that class when some interesting thing happens to an object.
http://msdn.microsoft.com/en-us/library/aa645739%28v=vs.71%29.aspx
A method is a code block containing a series of statements. In C#, every executed instruction is done so in the context of a method.
http://msdn.microsoft.com/en-us/library/ms173114%28v=vs.80%29.aspx
Related
I am working on a project, where I have to invoke a method when a value gets below a certain threshold. This event then writes some information to the user.
I have decided to put it in the setter, as it should be displayed when the user tries to get information.
The problem is that I still want to get something afterwards (as it is a getter), but I get stackoverflow and I can see that the getter is called many times. I thought this was weird, since the .invoke should only invoke the event and then move on. So how can i move further from the invoke, instead of having it go back to the beginning of the setter every time it is called,
This is the current setter:
get
{
if (_balance <= BalanceThreshold)
UserBalanceNotification.Invoke(this,BalanceThreshold);
return _balance;
}
And this is the general event:
public delegate void UserBalanceNotification(User user, int balanceThreshold);
As this is a more general question I doubt more code snippet would support it
I have the following code and am wondering how to break it down? It works great but was written by a guru and is over my head. Thank you in advance for any help.
The code basically writes device information sent and received to the GUI. It seems like it has events created based on the device and also invokes GUI stuff.
Why would you need to invoke?
I guess I'm wondering if this is overly complicated or appropriate? What may be a better way to accomplish the same task?
I'm also wondering what the "delegate { };" does?
public event EventHandler CommunicationPerformed = delegate { };
SerialPort _port;
readonly int _delay = 100;
private string ReadAndUpdateStatus()
{
string read = _port.ReadExisting();
CommunicationPerformed?.Invoke(this, new LoaderReadWriteEventArgs(read, LoaderCommunicationDirection.Read));
return read;
}
private void WriteAndUpdateStatus(string data)
{
if (!data.StartsWith("//")) //ignore "Comment" lines but show them on the GUI to read
_port.Write(data);
CommunicationPerformed?.Invoke(this, new LoaderReadWriteEventArgs(data, LoaderCommunicationDirection.Write));
}
public class LoaderReadWriteEventArgs : EventArgs
{
public LoaderCommunicationDirection Direction { get; }
public string Value { get; }
public LoaderReadWriteEventArgs(string value, LoaderCommunicationDirection direction)
{
Value = value;
Direction = direction;
}
}
public enum LoaderCommunicationDirection
{
Read,
Write
}
You asked three questions, and as usual, only one of them got answered. Try to ask only one question in your question.
I'm also wondering what the delegate { } does?
public event EventHandler CommunicationPerformed = delegate { };
As the other answer notes, events are null by default in C#. This technique makes an event handler that does nothing, but is not null.
There are, unfortunately, many syntaxes for an anonymous function in C#. delegate {} means "give me a do-nothing function that matches any non-ref-out formal parameter list that is void returning". That's why people do delegate{}, because it works almost anywhere in a context where an event handler is expected.
I think you need to review this https://learn.microsoft.com/en-us/dotnet/standard/events/.
Why would you need to invoke?
To broadcast to event handlers (any party who registered for this event get notified this way)
I guess I'm wondering if this is overly complicated or appropriate?
*What may be a better way to accomplish the same task?
This is not complicated. This is pretty much as easy as it gets.*
I'm also wondering what the "delegate { };" does?
my two cents.
I dont know which code line you are refering but a delegate is a type that holds a reference to a method. A delegate is declared with a signature that shows the return type and parameters for the methods it references, and can hold references only to methods that match its signature. A delegate is thus equivalent to a type-safe function pointer or a callback. A delegate declaration is sufficient to define a delegate class.
orhtej2 answered your first question quite nicely. Using the explicit Invoke method allows you to leverage the null conditional operator, which reduces the code to fire the event a single line.
As for whether this is overly complicated: No, that's basically how events are done.
What I've sometimes seen (especially in combination with the INotifyPropertyChanged interface in MVVM patterns) are helper methods, which encapsulate the longer, but more obvious pre-C#6 code and let you fire the event with less plumbing.
private void FireCommPerformed(string value, LoaderCommunicationDirection direction)
{
EventHandler handler = CommunicationPerformed;
if (handler != null)
{
handler(this, new LoaderReadWriteEventArgs(value, direction)));
}
}
You could then use it like this:
private string ReadAndUpdateStatus()
{
string read = _port.ReadExisting();
FireCommPerformed(read, LoaderCommunicationDirection.Read);
return read;
}
The Delegate { } is simply an empty delegate, like a null for events. Unless some other method in the code subscribes to the CommunicationPerformed event of this class during runtime, nothing will happen when the event is fired.
Let's focus in on what is exactly happening here. This should help you figure out everything else.
CommunicationPerformed?.Invoke(this, new LoaderReadWriteEventArgs(read, LoaderCommunicationDirection.Read));
This is checking to see if the delegate (event handlers are delegates) (CommunicationPerformed) is null.
Delegates are pointers (but with extra functionality).
If the delegate (pointer) is null, it means that nothing has been assigned to it.
Pointers store memory locations. In this case, it makes a memory reference to the function 'this'. 'This' is a reference to ReadAndUpdateStatus().
So this line basically says: "since the pointer is null, have this pointer reference the ReadAndUpdateStatus() function".
But what about the event args? Well... This is where delegates diverge from pointers.
Delegates don't just safely hold and store memory locations. They also can hold parameters.
You use a class that extends from EventArgs as the way of passing in a list of parameters.
From here, the event handler (event handlers are delegates) CommunicationPerformed will coordinate sending that list of arguments to whatever functions require it.
These functions are called whenever CommunicationPerformed is invoked (e.g. told to run). This is typically indicated with a:
+=CommunicationPerformed(foo,bar)
Now - why would use event handlers (or any delegate - for that matter)?
They're verbose and annoying to read (way more work than writing a simple bool and a trigger function), they don't look like other function, and they're frankly weird - right?
Except that they're really useful. Here's how:
1.) They work a lot like Tasks. You can invoke them in Parallel, in loops, wherever. They keep consistent state. They don't "bleed" and cause bugs.
2.) They're pointers. Guaranteed pass-by-reference. Except, they're magical, and if you stop using the delegate, they won't linger in memory.
3.) They allow you to control state in loops. Sometimes, a bool trigger won't work properly if you're in a really tight loop. You fire an event? Guaranteed behavior that your trigger will only be fired once.
I'm gonna try to answer #1 and #2 (3 is already covered).
#1 - At some point, someone decided that other parts of the program could subscribe to an event that tells them when communication has been performed. Once that decision has been made, it's kind of a "contract". You perform the communication->you fire the event that notifies subscribers that communication has been performed. What those subscribers are doing about that, or why they need to know...Actually not really any of your concern if this class is your focus. In theory, at least. And often that's really practically the case. If your class is doing its job, it's not really your concern who is listening to the events.
#2 - I do think the method of declaring events and event handlers in your code is overly complicated. Plenty of people (and official Microsoft best practices) disagree with me. You can google "why should my event handlers use eventargs" and read plenty on the subject. Or Look here. Another approach is the following:
public event Action<string, LoaderCommunicationDirection> CommunicationPerformed;
void PerformWrite()
{
string myComm = "String I'm sending";
//Line of code that performs communication that writes string here
CommunicationPerformed?.Invoke(myComm, LoaderCommunicationDirection.Write);
}
This is much more succinct than having an entire class that derives from EventArgs. However, it has the very obvious drawback that if you are an event subscriber...you have no idea what string is. Of course, since it's named value in your code...that's not much more helpful. And a comment above the event declaration is just about as useful.
i have a class that has a ConcurrentDictionary as a private member.
This class also defines a delegate/call back method.
The base class registers this method as the callback for an external event. this is one only ONCE.
I am running ANT memory profiler and i'm seeing 1000s of instances of MyObj referenced from hundreds of instances of the ConcurrentDictionary property. The GC root for these is the event callback.
This seems to be causing memory to rise significantly as the application runs..after maybe about 5 min or so, a good portion of that memory is reclaimed, but i'm worried that the app could potentially run into issue since it swells sto quickly and for so long before GC kicks in.
What's going on here and how do i resolve?
This is a snippet of the base calls that registers the handler
protected abstract void DataReceivedEventHandler(DataChangedEvent evt);
public virtual void RegisterForChanges(ICollection<MemoryTable> tables)
{
foreach (MemoryTable table in tables)
{
_subscribedTables.Add(table);
table.RegisterEventListener(new DataChangedCallBack(this.DataReceivedEventHandler));
}
}
Here is the handler which is implemented in a subclass of the above mentioned baseclass:
private ConcurrentDictionary<string, DataRecord> _cachedRecords;
protected override void DataReceivedEventHandler(DataChangedEvent evt)
{
DataRecord record = evt.Record as DataRecord;
string key = record.Key;
if (string.IsNullOrEmpty(key)) { return; }
if (_cachedRecords.ContainsKey(key))
{
_cachedRecords[key] = record;
DateTime updateTime = record.UpdateTime;
TimeSpan delta = updateTime - _lastNotifyTime;
if (delta.TotalMilliseconds > _notificationFrequency)
{
PublishData(updateTime);
}
}
}
The publishData method publishes prism events
What's going on
Yes, events are a list of delegates, which have two relevant fields: target and method. Unless you are referencing a static method, target is a reference to the class. And method is a reflection MemberInfo which tells the event which method to call.
How to troubleshoot
Consider putting a breakpoint in the add_EventName method. (If you don't have an explicit add_EventName and remove_EventName, you would have to redefine your event with this explicit code).
private event EventHandler eventName;
public event EventHandler EventName
{
add { eventName += value; } // Breakpoint here
remove { eventName -= value; }
}
This will help you find why it is subscribed so many times.
A delegate contains a strong reference to an object along with an indication of what method to call on that object. A live object which holds a strong reference to a delegate will thus keep alive the object upon which the delegate will operate (as well as any objects to which that object holds strong references).
Sometimes one will wish to register a callback or event which will operate on an object for the benefit of some other object, but the callback or event shouldn't keep the object alive solely for its own sake. For example, an object might wish to keep a count of how many times some long-lived object raises a particular event, and thus create an instance of an "event counter" object which it attaches to the event. As long as the long-lived object holds the event subscription for the counter object, that counter object will be kept alive and the counter will get incremented every time the event is raised. Of course, if everybody who would ever have looked at the counter has ceased to exist, neither the counter, nor the effort required to increment it, will serve any useful purpose.
If one has a callback which one expects will be fired at some definite point in the future, but the callback would only serve a useful purpose if some live reference (outside the callback itself) exists to the object upon which it would operate, it may be useful to have the callback registered to a forwarding object which would in turn forward the call to the main object if doing so would make sense. The simplest way to accomplish that is to have the forwarding object hold a WeakReference. When the forwarding object receives a call, it retrieves the Target from the WeakReference. If that's non-null, it casts the retrieved target to the main object's type and calls the appropriate method on it. If the main object ceases to exist before the callback executes, the WeakReference.Target property will be null, and the forwarding object's callback will simply return silently.
A couple of further notes: (1) it might be tempting to set the Target of the WeakReference to a delegate and call that, but that approach will only work if the real target object itself holds a reference to that delegate; otherwise, the delegate itself will be eligible for garbage-collection even if its target isn't; (2) it may be helpful to cast the WeakReference to an interface, and have the main object implement that interface. This would allow one forwarding-object class to be used with many other classes. If one class might want to be attached to a number of weak events, it may be helpful to use a generic interface:
interface IDispatchAction<DummyType,ParamType>
{
void Act(ParamType ref param);
}
That would allow the main object to expose a number of IDispatchAction actions (e.g. if if a class implements IDispatchAction<foo,int>.Act and IDispatchAction<bar,int>.Act, then casting a reference to that class to one of those interfaces and calling Act upon it will invoke the appropriate method).
After the external event is raised the one time, unsubscribe your class from it (SomeClass.SomeEvent -= MyEventHandler), or you can look at using WeakReferences
Is it possible that you are re-subscribing tables over and over again? I see this:
foreach (MemoryTable table in tables)
{
_subscribedTables.Add(table);
table.RegisterEventListener(new DataChangedCallBack(this.DataReceivedEventHandler));
}
and I'd expect to see a check to make sure that tables are not being re-subscribed:
foreach (MemoryTable table in tables)
{
if (!_subscribedTables.Contains(table)) {
_subscribedTables.Add(table);
table.RegisterEventListener(new DataChangedCallBack(this.DataReceivedEventHandler));
}
}
EDIT: Given the comments at the beginning of the question, I am fairly confident that the problem (if you can call it a problem) lies here:
if (_cachedRecords.ContainsKey(key))
{
_cachedRecords[key] = record;
What you are saying here is that if the record's key already exists in cachedRecords, then replace the value with the (presumably) new row instance. This is probably because some background process caused the row's data to be changed and you need to propagate those new values to the UI.
My guess is that the MemoryTable class is creating a new instance of DataRecord for these changes, and sending that new instance up the event chain to the handler we see here. If the event is fired thousands of times, then of course you are going to end up with thousands of them in memory. The garbage collector is usually pretty good about cleaning these things up, but you might want to consider in-place updates to avoid the massive GC that will occur when these instances get collected.
What you should not do is try to control (or even predict) when the GC is going to run. Just make sure that after the GC collects, the excess objects are gone (in other words, make sure that they are not being leaked) and you will be alright.
If we want that the object defined callback method should not stay in memory, we have to define this method as Static.
In the program I am creating, I have a large amount of enums
enum kEvents
{
Start = 0,
End,
EntityCreated,
}
In this program, there is a huge list of Entities.
Each entity holds a list of "kEvents" that it is "Registered to"
Every time an object says "Call the Start event" I have to iterate through every single entity in the game, and find out if they are "listening" for that event.
Note: I know that c# has event handlers, but I was hoping to create this enum system from the ground up instead.
This being the case, what is the best way to:
Hold the collection of enums in each entity object
Check if the entity holds the triggered enum
I am wondering if Enums, being basically numbers, have a lower level, quicker way to handle this than a List<T> of objects.
Every time an object says "Call the Start event" I have to iterate through every single entity in the game, and find out if they are "listening" for that event.
You're doing it wrong! Iterating over every single object and checking if they're registered for an event is very inefficient! This is the typical Observer design pattern and there are several ways to go about this, here are a couple:
Have a single event which gets raised and has an enum parameter for event type (every subscriber gets it).
Have a dictionary of enums and corresponding events.
Here is what option 1 might look like:
delegate void OnEventDelegate(kEvents anEvent);
public class MyEventObservable
{
public event OnEventDelegate OnEvent;
}
public class MyEventObserver
{
// Constructors and all
// ...
public void OnEventReceived(kEvents anEvent)
{
switch(anEvent)
{
// switch through all the events and handle the ones that you need
}
}
}
MyEventObserver observer = new MyEventObserver();
MyEventObservable observable = new MyEventObservable();
observable.OnEvent += new OnEventDelegate(observer.OnEventReceived);
Here is option 2:
public class MyEventObservable
{
private Dictionary<kEvents, List<IObserver>> _observers;
MyEventObservable()
{
// Initialize the dictionary with all the events
}
public void RegisterObserver(kEvents event, IObserver observer)
{
_observers[event].Add(observer);
}
}
interface class IObserver
{
void Notify(kEvents anEvent);
}
public MyEventObserver: IObserver
{
// Constructors and all
// ...
// Override the IObserver
public void Notify(kEvents anEvent)
{
switch(anEvent)
{
// switch through all the events and handle the ones that you need
}
}
}
MyEventObserver observer = new MyEventObserver();
MyEventObservable observable = new MyEventObservable();
observable.RegisterObserver(kEvents.Start, observer);
Option two will reduce the number of events each observer has to handle, but it comes at the cost of having to register for every event separately (which adds coding complexity). This means that option 2 will work faster because there are fewer function calls to make. Depending on how "crazy" you want to get with the performance, there might be other options that can help you to speed it up but this should set you on the right track.
P.S. I have not compiled any of the code, but it should give you a general idea of how things ought to work.
It seems to me that you want to implement some kind of publish/subscribe scheme, some centralized event sink that the Entities can subscribe to events and provide a callback when that event happens, then other Entities would Rise the event and the event sink would call all the Entities that are subscribed to that event.... but I may have not understood the question :)
Something like:
How to access controls in other class
Every time an object says "Call the Start event" I have to iterate
through every single entity in the game, and find out if they are
"listening" for that event.
If I have correctly understood what you are doing then you are doing it backwards. the knowledge of which events an entity is listening to cannot be (only) in the event itself. There must be another data structure that holds this information.
That other data structure could be something as simple as a Map from the enum constant to a list of entities.
When using a Delegate, I can use Delegate.GetInvocationList() Method to retrieve the invocation list of the delegate at runtime.
Is there a way to access the subscriber list that has been associated with an event? I ran the code from this example (SO#1237001) and the immediate window allowed me to cast the SecondChange event to a System.MultiCastDelegate and then invoke the GetInvocationList method.
However, in my scenario I am working with a System.Windows.Forms.DataGridView and I would like to inspect the invocation list of the CellClick event at runtime. However, when I try any kind of cast on CellClick, I recieve the following error:
The event
'System.Windows.Forms.DataGridView.CellClick'
can only appear on the left hand side
of += or -=
I can see there are clearly differences in the declarations of these events. In the Clock example the event is declared like this:
public event Func<DateTime, bool> SecondChange;
And in the DataGridView the event is declared like this:
[SRDescription("DataGridView_CellClickDescr"), SRCategory("CatMouse")]
public event DataGridViewCellEventHandler CellClick
{
add
{
base.Events.AddHandler(EVENT_DATAGRIDVIEWCELLCLICK, value);
}
remove
{
base.Events.RemoveHandler(EVENT_DATAGRIDVIEWCELLCLICK, value);
}
}
Why can one call GetInvocationList on the Clock example, but not on the DataGridView event? Is there any way for me to get the same type of information from the DataGridView event that GetInvocationList returns?
The whole point of an event it defines (only) an add/remove API (like how a property defines get/set).
The entire point of an event is that externally you can't do this (access the subscribers). I'm guessing that in the "clock" example, the code that accesses the list is inside the type that declares the event; that is fine: inside the type, you have full access to the backing implementation (often a delegate field).
Externally, you should only care about your own handlers, that you already know about because you subscribed them. Attempts to fetch the backer exist, but it is brittle and not recommended. In this case, it uses an EventHandlerList, for example.
Why do you need this? It usually means that you are doing something wrong (sorry, but it does).