What does SetValue do in this particular event? - c#

I am new to events and I am trying to see how an event works and what purpose they would have. The code below is some code that a friend helped me with that we found on the net. It works but I am not certain as to how the event is used.
In the Main method there is the EventTest which creates a new object e which then intern calls SetValue method twice with a different parameter.
static void Main(string[] args)
{
EventTest e = new EventTest(5);
e.SetValue(7);
e.SetValue(11);
Console.ReadKey();
}
The following code is actually the event code.The OnNumChanged is the event that writes information if the number is changed. So when SetValue(100) is set to a different number then the event is fired.
Question: When the SetValue is set with a new value this is what cause the event to change correct?
I am just new enough to the event change that I could really use some good examples or have someone really explain this example line by line.
e.SetValue(7);
e.SetValue(11);
protected virtual void OnNumChanged()
{
if (ChangeNum != null)
{
ChangeNum();
}
else
{
Console.WriteLine("Event fired!");
}
}
Code:
class Program
{
static void Main(string[] args)
{
EventTest e = new EventTest(5);
e.SetValue(7);
e.SetValue(11);
Console.ReadKey();
}
}
public class EventTest
{
private int value;
public delegate void NumManipulationHandler();
public event NumManipulationHandler ChangeNum;
public EventTest(int n)
{
SetValue(n);
}
public void SetValue(int n)
{
if (value != n)
{
value = n;
OnNumChanged();
}
}
protected virtual void OnNumChanged()
{
if (ChangeNum != null)
{
ChangeNum();
}
else
{
Console.WriteLine("Event fired!");
}
}
}

Yes, you are correct:
public void SetValue(int n)
{
if (value != n) // check if the value actually changed
{
value = n;
OnNumChanged(); // call the event "in a save way", see below
}
}
protected virtual void OnNumChanged()
{
if (ChangeNum != null) // check if someone is listening - PROBLEM: see below
ChangeNum(); // trigger the event and call all event handlers registered
}
The Problem I mentioned above: You get the event to check it for null and then get it again to execute. In a multi-threaded environment it can happen, that between these two "gets" it changes => create a local copy:
protected virtual void OnNumChanged()
{
var changeNum = ChangeNum;
if (changeNum != null)
changeNum();
}
To actually get notified on the event you need to register for the event e.g. like this:
static void Main(string[] args)
{
EventTest e = new EventTest(5);
e.ChangeNum += () => Console.WriteLine("Num changed"); //<== this
e.SetValue(7);
e.SetValue(11);
Console.ReadKey();
}
It also would make more sense to also supply the new value in the event. That can be done by altering the delegate to:
public delegate void NumManipulationHandler(int newValue);
and call it like:
ChangeNum(value);
Then you can register like:
e.ChangeNum += newValue => Console.WriteLine("Num changed to " + newValue);

in short: yes! if the value that is passed along with the SetValue method differs from the one that was already stored, an event is fired, indicating the change as such.
Any other code that might be subscribed to such an event can then react accordingly in whatever way.
Even though I myself can learn easier from video (and I advise you to search for videos on events in C# as well), it all boils down to a way for a class to provide notifications to clients of that class when some interesting thing happens to an object (further reading here)

Related

Can I be notified when a listener unsubscribes?

Summary
I have a simple class that exposes a property of type ReadOnlyObservableCollection.
When this property is accessed for the first time, quite a bit of data is generated.
The generated data is time dependent and so will change over time - hence the need for the property to be of type ReadOnlyObservableCollection.
This is working as expected, however the generated dataset is large enough that over the lifetime of the application it is guaranteed I will run into memory issues.
Problem
I need to be able to delete the references to the generated data so it can be collected by the GC. The thing is though, I cannot do this unless I know that there are no listeners on the ReadOnlyObservableCollection - or more precisely the underlying INotifyCollectionChanged.CollectionChanged event.
Is there a way I can easily be notified when a listener unsubscribes from an event without implementing said event?
One way around it which would be rather simple but perhaps a bit hacky is to keep track of all Storage objects that have active data and every so often call the CleanDataSet method if there are no listeners to the INotifyCollectionChanged.CollectionChanged event.
Sample Code
public class Storage
{
//The regular computation of the data set is not shown as it is not relevant
//to the issue at hand.
public ReadOnlyObservableCollection<String> Data
{
get
{
if (DataList == null)
{
DataList = new ObservableCollection<String>();
DataReadOnly = new ReadOnlyObservableCollection<String>(DataList);
ComputeDataSet();
//I require a way of 'listening' when the
//DataList.CollectionChanged gains or loses a subscriber.
}
return DataReadOnly;
}
}
private ReadOnlyObservableCollection<String> DataReadOnly;
private ObservableCollection<String> DataList;
private void ComputeDataSet()
{
Random random = new Random();
for (Int32 counter = 0; counter < 10000; counter++)
DataList.Add(random.Next().ToString());
}
private void CleanDataSet()
{
DataReadOnly = null;
DataList = null;
}
}
You can use the fact that ReadOnlyObservableCollection.CollectionChanged is virtual, and an event returns null if there are no subscribers:
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
public class Program
{
public static void Main()
{
var innerCollection = new ObservableCollection<string>() { "foo", "bar" };
var collection = (INotifyCollectionChanged)new MyReadOnlyObservableCollection<string>(innerCollection);
collection.CollectionChanged += Handler;
innerCollection.Add("baz");
collection.CollectionChanged -= Handler;
}
private static void Handler(object sender, NotifyCollectionChangedEventArgs e)
{
Console.WriteLine(e.NewItems[0]);
}
}
public class MyReadOnlyObservableCollection<T> : ReadOnlyObservableCollection<T>
{
public MyReadOnlyObservableCollection(ObservableCollection<T> list) : base(list) { }
private event NotifyCollectionChangedEventHandler InnerEvent;
protected override event NotifyCollectionChangedEventHandler CollectionChanged
{
add
{
if (InnerEvent == null)
{
Console.WriteLine("Got our first subscriber");
}
InnerEvent += value;
}
remove
{
InnerEvent -= value;
if (InnerEvent == null)
{
Console.WriteLine("There are no more subscribers");
}
}
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
{
InnerEvent?.Invoke(this, args);
}
}
We override the CollectionChanged event, and provide our own add and remove handlers. These handlers delegate to an inner event (we could just have used a delegate here, but an event's += is thread-safe, whereas a delegate's is not). In the remove handler, we also test to see whether the inner event is null: if it is, there are no more subscribers.
We also need to override OnCollectionChanged to call our inner event.
At this point we've almost rewritten ReadOnlyObservableCollection, however: it's not a big class.

Declare callback event handlers correctly

I have a simple delegate, event and property allowing me to create callback subscriptions on events:
public static class Test
{
/// <summary>Delegate for property changed event</summary>
public delegate void TestEventHandler();
/// <summary>Event called when value is changed</summary>
public static event TestEventHandler OnTestHappening;
/// <summary>Property to specify our test is happening</summary>
private static bool testHappening;
public static bool TestHappening
{
get
{
return testHappening;
}
set
{
testHappening = value;
// Notify our value has changed only if True
// ie. Only fire an event when we're ready as we'll hook methods to the Event that must only fire if ready
if ( value )
{
if ( OnTestHappening != null )
OnTestHappening();
}
}
}
}
I can then easily subscribe and unsubscribe to the event and fire the event callbacks as needed:
public class Tester
{
private void Main()
{
Testing();
// Start the test
Test.TestHappening = true;
}
private void Testing()
{
// Unsubscribe from event
Test.OnTestHappening -= Testing;
// Check if we're busy testing yet
if ( !Test.TestHappening )
{
// Subscribe to event
Test.OnTestHappening += new Test.TestEventHandler( Testing );
return;
}
// Do stuff here....
}
}
When compiling, code analysis gives me, "CA1009: Declare event handlers correctly?" and I've searched high and low and found many questions, articles etc but none that feel like they address my scenario. I can't seem to find a concrete starting point for the conversion and I'm starting to wonder if I'm meant to completely rewrite the implementation?
Edit: Firstly I really appreciate the assists, I did look carefully through all the sites I could before posting this and I did see (and try work with) each of the links that you all posted. I even went back and studied delegates and events again but I feel like I'm missing the starting point somehow because each time I try change a part of it, I just keep producing errors that I can't come back from like:
public delegate void TestEventHandler( object sender, EventArgs e );
With the other links I visited, I could only find 1 similarity to my code (either in the delegate, the handler or the property) but couldn't find anything that related enough to mine to actually instil that "eureka" moment
Edit 2: I have now rebuilt my example with what "looks" to be the correct standard but this code is so fugly it looks like it was beaten with a confogulus stick and dipped in a tank of confutious before being deep fried in horriduculous:
public static class Test
{
/// <summary>Delegate for property changed event</summary>
public delegate void TestEventHandler( object sender, EventArgs e );
/// <summary>Event called when value is changed</summary>
public static event TestEventHandler OnTestHappening;
/// <summary>Property to specify our test is happening</summary>
private static bool testHappening;
public static bool TestHappening
{
get
{
return testHappening;
}
set
{
testHappening = value;
// Notify our value has changed only if True
// ie. Only fire an event when we're ready as we'll hook methods to the Event that must only fire if ready
if ( value )
{
if ( OnTestHappening != null )
OnTestHappening( null, EventArgs.Empty );
}
}
}
}
public class Tester
{
private void Main()
{
Testing( this, EventArgs.Empty );
// Start the test
Test.TestHappening = true;
}
private void Testing( object sender, EventArgs e )
{
// Unsubscribe from the event
Test.OnTestHappening -= Testing;
// Check if we're busy testing yet
if ( !GlobalClass.SystemOnline )
{
// Subscribe to the event
Test.OnTestHappening += new Test.TestEventHandler( Testing );
return;
}
// Do stuff here....
}
}
Please tell me I've missed something and that there is in fact a more elegant implementation
Edit 3 : Based on the code by Enigmativity, I've reworked the code to it's most basic form. I've also moved the code setting the variable to true in a different method so it doesn't look so daft sitting in Main.
public static class Test4
{
/// <summary>Event called when value is changed</summary>
public static event EventHandler TestHappening;
/// <summary>Property to specify our test is happening</summary>
private static bool test = false;
public static bool Test
{
get
{
return test;
}
set
{
// Notify our value has changed only if True
// ie. Only fire an event when we're ready as we'll hook methods to the Event that must only fire if ready
if ( value )
{
TestHappening( null, EventArgs.Empty );
}
}
}
}
public class Tester4
{
private void Main()
{
Testing( this, EventArgs.Empty );
}
private void Testing( object sender, EventArgs e )
{
// Unsubscribe from the event
Test4.TestHappening -= Testing;
// Check if we're busy testing yet
if ( !Test4.Test )
{
// Subscribe to the event
Test4.TestHappening += Testing;
return;
}
// Do stuff here....
}
private void SomeMethodCalledFromSomewhere()
{
// Set the value to true and thereby start the test
Test4.Test = true;
}
}
Would this be considered good code or should I rather have the OnTestHappening method as defined in Enigmativity's code?
Why can't I use a parameterless delegate? It's now using the default ( object sender, EventArgs e ) but that feels overkill and doesn't make sense why the compiler is happy with it but according to coding standards it's considered bad code? I'm not arguing the standard but rather trying to understand it's reasoning.
As per Storm's request, here is how I would most likely structure the code. It's more inline with the standard conventions.
public static class TestClass
{
public delegate void TestEventHandler(object sender, EventArgs e);
public static event TestEventHandler TestHappening;
private static bool test = false;
public static bool Test
{
get
{
return test;
}
set
{
test = value;
if (test)
{
OnTestHappening();
}
}
}
private static void OnTestHappening()
{
var handler = TestHappening;
if (handler != null)
handler(null, EventArgs.Empty);
}
}
And Tester would look like this:
public class Tester
{
public void Main()
{
TestClass.TestHappening += Testing;
Go();
}
private void Testing(object sender, EventArgs e)
{
Console.WriteLine(TestClass.Test);
TestClass.TestHappening -= Testing;
}
private void Go()
{
TestClass.Test = true;
}
}
Calling it would look like this:
var tester = new Tester();
tester.Main();
Running this outputs True to the console.
If I were writing this in a more standard way, it would look like this:
public class TestEventArg : EventArgs
{
public TestEventArg(bool updatedValue)
{
this.UpdatedValue = updatedValue;
}
public bool UpdatedValue { get; private set; }
}
public class TestClass
{
public event EventHandler<TestEventArg> TestHappening;
private bool test = false;
public bool Test
{
get { return test; }
set
{
var old = test;
test = value;
if (test != old)
OnTestHappening(test);
}
}
private void OnTestHappening(bool updatedValue)
{
var handler = TestHappening;
if (handler != null)
handler(this, new TestEventArg(updatedValue));
}
}

C# Invoke an event [duplicate]

This question already has an answer here:
C# Handle Event
(1 answer)
Closed 8 years ago.
I have created this program here to demonstrate what i am trying to do. You can see that all the code is already written except the line where the _OnSell event should be invoked. (Line 21~)
using System;
namespace example
{
public class Car
{
public int Price;
public string ModelName;
private Boolean Sold;
public delegate void SellEventHandler(string str);
public event SellEventHandler _OnSell;
public Boolean _Sold
{
get { return Sold; }
set
{
Sold = value;
if (Sold == true)
{
// INVOKE _OnSell EVENT HERE !!
}
}
}
public void OnSell(string str)
{
Console.WriteLine("library stuff");
}
public Car(int price, string modelname)
{
Price = price;
ModelName = modelname;
Sold = false;
_OnSell = OnSell;
}
}
public class Program
{
static void Main()
{
Program p1 = new Program();
Car _car = new Car(6000, "audi");
_car._OnSell += p1.Car_OnSell;
_car._Sold = Console.ReadLine() == "true" ? true : false;
Console.ReadLine();
}
public void Car_OnSell(string message)
{
Console.WriteLine("user stuff");
}
}
}
I am trying to invoke the event _car._OnSell whenever the value _car._Sold is changed. How can i do that in C# ?
See Handling and Raising Events
Thus, following the example provided, the code would look like the following.
Note the name changes for a cleaner public API and de facto consistency and naming standards.
public class Car
{
// Note use of `sender` convention
public delegate void SoldEventHandler(object sender, string str);
// Events normally do not have the `On` prefix, also the event
// name is normally the sense-correct verb such as `Sold` or `Selling`.
public event SoldEventHandler Sold;
private bool _isSold;
public bool IsSold
{
get { return _isSold; }
set
{
if (value && !_isSold) {
// Only sell when false -> true
OnSold("whatever string it is supposed to be");
}
_isSold = value;
}
}
// "Typically, to raise an event, you add a method that is marked as protected and virtual.
// .. Name this method OnEventName; for example, OnDataReceived."
public virtual void OnSold(string str)
{
// Follow the conventions in the link - ask on SO as to why the local
// variable and check for null are important/necessary.
var handler = Sold;
if (handler != null) {
handler(this, str);
}
}
// ..
_car.Sold += p1.Car_OnSell;
_car.IsSold += Console.ReadLine() == "true" ? true : false;
In most cases I would recommend having the event take (object sender, EventArgs args) as it makes future changes to the event much more flexible - this is also discussed in the link.
As explained in the links offered by commenters (but unfortunately not explained in the first answer that was posted), you need to change your code so that it looks more like this:
public Boolean _Sold
{
get { return Sold; }
set
{
Sold = value;
if (Sold)
{
OnSell("your string here");
}
}
}
public void OnSell(string str)
{
SellEventHandler handler = _OnSell;
if (handler != null)
{
handler(str);
}
Console.WriteLine("library stuff");
}
The above will work. However, it's worth noting that you're deviating from the normal .NET event-handling idioms in a couple of important ways:
Your event delegate does not follow the EventHandler<T> structure. The normal .NET method signature offers two advantages: identification of the sender, and a standardized EventArgs data structure on which to base your event arguments.
You are raising the event only when the property is set to true. More typical, and frankly more useful, is a "changed" event. E.g. SoldChanged, which would be raised any time the value of the Sold property was changed.
One of the nicer benefits of following the standard event-handling idioms is that your class will work with most if not all of the common data binding implementations in .NET. The way you have it implemented here, your event is very limited in the way it can be used. That might be fine in this scenario, but as a general rule it's so easy to provide more flexible implementation, you might as well get in the habit of doing so.
Try this:
_OnSell( "some message" );

Why use events for what I can do with Delegates?

I know Events are always associated with Delegates. But, I am missing some core use of Events, and trying to understand that.
I created a simple Event program, as below, and it works perfectly fine.
namespace CompleteRef3._0
{
delegate void someEventDelegate();
class EventTester
{
public event someEventDelegate someEvent;
public void doEvent()
{
if (someEvent != null) someEvent();
}
}
class Program
{
static void EventHandler1()
{
Console.WriteLine("Event handler 1 called..");
}
static void EventHandler2()
{
Console.WriteLine("Event handler 2 called..");
}
static void EventHandler3()
{
Console.WriteLine("Event handler 3 called..");
}
static void Main(string[] args)
{
EventTester evt = new EventTester();
evt.someEvent += EventHandler1;
evt.someEvent += EventHandler2;
evt.someEvent += EventHandler3;
evt.doEvent();
Console.ReadKey();
}
}
}
I replaced the event declaration with delegates. That is I replaced the line public event someEventDelegate someEvent; with someEventDelegate someEvent; on the above program, and I still get the same result. Now, I was confused why we need to use Events, if it can be achieved by Delegates only. What is the real use of Events?
The modified program without events is as below -
namespace CompleteRef3._0
{
delegate void someEventDelegate();
class EventTester
{
someEventDelegate someEvent;
public void doEvent()
{
if (someEvent != null) someEvent();
}
}
class Program
{
static void EventHandler1()
{
Console.WriteLine("Event handler 1 called..");
}
static void EventHandler2()
{
Console.WriteLine("Event handler 2 called..");
}
static void EventHandler3()
{
Console.WriteLine("Event handler 3 called..");
}
static void Main(string[] args)
{
EventTester evt = new EventTester();
evt.someEvent += EventHandler1;
evt.someEvent += EventHandler2;
evt.someEvent += EventHandler3;
evt.doEvent();
Console.ReadKey();
}
}
}
Imagine you have 3 subscribers who are interested in your someEvent. Let's further imagine they are interested in receiving events from the same EventTester instance. For brevity, let's leave out the details of how the exact same instance is passed to all the clients. When I say clients, I mean any class who is a subscriber to the event.
Here is the instance:
EventTester evt = new EventTester();
They have subscribed to the event of the above instance as shown below:
Client 1
evt.someEvent += Client1Handler1;
evt.someEvent += Client1Handler2;
Client 2
evt.someEvent += Client2Handler1;
Client 3
evt.someEvent += Client3Handler1;
evt.someEvent += Client3Handler2;
Client 4:
Imagine client 4 did one of the 3 below:
// 1: See Note 1 below
evt.someEvent = null;
// 2: See Note 2 below
evt.someEvent = new someEventDelegate(MyHandler);
// 3: See Note 3 below
evt.someEvent();
//...
private void MyHandler()
{
MessageBox.Show("Client 4");
}
Note 1
Client 1, 2, and 3 will not be getting any events anymore. Why? Because Client 4 just did this evt.someEvent = null; and in EventTester you have this line of code:
if (someEvent != null) someEvent();
Since that condition will not pass anymore, no event will be raised. There is nothing wrong with the above line of code by the way. But there is the problem with using delegates: It can be assigned to.
Note 2
It has been completely over-written to a brand new instance. Now regardless of the client, they will all see a message box that says "Client 4".
Note 3
Ooops all of a sudden one of the clients is broadcasting the event.
Imagine for a second EventTester was a Button and someEvent was Click. Imagine you had multiple clients interested in the click event of this button. All of a sudden, one client decides no-one else should get notifications (Note 1). Or one client decides that when the button is clicked, it will be handled only 1 way (Note 2). Or it has made the decision that it will decide when a button is clicked even though the button may not have been clicked (Note 3).
If you have an event and one of the clients tried the above, they will not be allowed and get a compile error, like this:
Sure, you can use delegates because behind the scenes an event is a construct that wraps a delegate.
But the rationale of using events instead of delegates is the the same as for using properties instead of fields - data encapsulation. It's bad practice to expose fields (whatever they are - primitive fields or delegates) directly.
By the way, you missed a public keyword before your delegate field to make it possible in the second snippet.
Another "by the way" with the second snippet: for delegates you should use Delegate.Combine instead of "+=".
The main purpose of events is to prevent subscribers from interfering with each other. If you do not use events, you can:
Replace other subscribers by reassigning delegate(instead of using the += operator),
Clear all subscribers (by setting delegate to null),
Broadcast to other subscribers by invoking the delegate.
Source: C# in a Nutshell
public class Program
{
public static void Main()
{
Number myNumber = new Number(100000);
myNumber.PrintMoney();
myNumber.PrintNumber();
Console.ReadKey();
}
}
public class Number
{
private PrintHelper _printHelper;
public Number(int val)
{
_value = val;
_printHelper = new PrintHelper();
//subscribe to beforePrintEvent event
_printHelper.beforePrintEvent += printHelper_beforePrintEvent;
}
//beforePrintevent handler
void printHelper_beforePrintEvent(string message)
{
Console.WriteLine("BeforePrintEvent fires from {0}", message);
}
private int _value;
public int Value
{
get { return _value; }
set { _value = value; }
}
public void PrintMoney()
{
_printHelper.PrintMoney(_value);
}
public void PrintNumber()
{
_printHelper.PrintNumber(_value);
}
}
public class PrintHelper
{
public delegate void BeforePrintDelegate(string message);
public event BeforePrintDelegate beforePrintEvent;
public PrintHelper()
{
}
public void PrintNumber(int num)
{
if (beforePrintEvent != null)
beforePrintEvent.Invoke("PrintNumber");
Console.WriteLine("Number: {0,-12:N0}", num);
}
public void PrintDecimal(int dec)
{
if (beforePrintEvent != null)
beforePrintEvent("PrintDecimal");
Console.WriteLine("Decimal: {0:G}", dec);
}
public void PrintMoney(int money)
{
if (beforePrintEvent != null)
beforePrintEvent("PrintMoney");
Console.WriteLine("Money: {0:C}", money);
}
public void PrintTemperature(int num)
{
if (beforePrintEvent != null)
beforePrintEvent("PrintTemerature");
Console.WriteLine("Temperature: {0,4:N1} F", num);
}
public void PrintHexadecimal(int dec)
{
if (beforePrintEvent != null)
beforePrintEvent("PrintHexadecimal");
Console.WriteLine("Hexadecimal: {0:X}", dec);
}
}

C#: Triggering an Event when an object is added to a Queue

I need to be able to trigger a event whenever an object is added to a Queue<Delegate>.
I created a new class that extends Queue:
public delegate void ChangedEventHandler(object sender, EventArgs e);
public class QueueWithChange<Delegate> : Queue<Delegate>
{
public event ChangedEventHandler Changed;
protected virtual void OnChanged(EventArgs e) {
if (Changed != null)
{
Changed(this, e);
}
}
}
And then attached the event from another class, like such:
QueueWithChange<TimerDelegate> eventQueue = new QueueWithChange<TimerDelegate>();
//
eventQueue.Changed += new ChangedEventHandler(delegate(object s, EventArgs ex) {
//This event is not being triggered, so this code is unreachable atm...and that is my problem
if (eventQueue.Count > 0)
{
eventQueue.Dequeue().Invoke(new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(5) });
actionTimer.Stop();
}
});
But whenever I enqueue an object (eventQueue.Enqueue(something)), the attached event is not being fired.
What am I missing here?
If you mean the non-generic Queue class, then you can just override Enqueue:
public override void Enqueue(object obj)
{
base.Enqueue(obj);
OnChanged(EventArgs.Empty);
}
However, if you mean the generic Queue<T> class, then note that there is no suitable virtual method to override. You might do better to encapsulate the queue with your own class:
(** important edit: removed base-class!!! **)
class Foo<T>
{
private readonly Queue<T> queue = new Queue<T>();
public event EventHandler Changed;
protected virtual void OnChanged()
{
if (Changed != null) Changed(this, EventArgs.Empty);
}
public virtual void Enqueue(T item)
{
queue.Enqueue(item);
OnChanged();
}
public int Count { get { return queue.Count; } }
public virtual T Dequeue()
{
T item = queue.Dequeue();
OnChanged();
return item;
}
}
However, looking at your code, it seems possible that you are using multiple threads here. If that is the case, consider a threaded queue instead.
I just did write up on what I call a TriggeredQueue. It's inspired the answer by Marc Gravell.
You can find my post here: http://joesauve.com/triggeredqueuet
And the Gist here: http://gist.github.com/jsauve/b2e8496172fdabd370c4
It has four events:
WillEnqueue
WillDequeue
DidEnqueue
DidDequeue
You can hook into any of these like so:
YourQueue.WillEnqueue += (sender, e) => {
// kick off some process
};
YourQueue.DidEnqueue += (sender, e) => {
// kick off some process
// e.Item provides access to the enqueued item, if you like
};
YourQueue.WillDequeue += (sender, e) => {
// kick off some process
};
YourQueue.DidDequeue += (sender, e) => {
// kick off some process
// e.Item provides access to the dequeued item, if you like
};
One neat trick is that you can use the DidDequeue method to kick off some process to ensure that the queue is full by making a web request or loading some data from a filesystem, etc. I use this class in Xamarin mobile apps to ensure that data and images are pre-cached in order to provide a smooth user experience, instead of loading images AFTER they scroll onto the screen (like you might see in Facebook and countless other apps).
try
public new void Enqueue(Delegate d)
{
base.Enqueue(d);
OnChanged(EventArgs.Empty);
}
You have to override Enqueue, to call OnChanged.

Categories

Resources