You have one EventOccured
delegate in which you will be notified of all events occurring in the EventStore
First, consider running the pre-code inside EventOccured
in a different dispatcher than the one in which the events are EventOccured
.
Secondly, is it possible to change this to an abstract class
with an implementation for FakeEventBase
, and then extend it and create separate instances for each type of FakeEvent
. It will be a much cleaner solution.
Third, consider creating a ThreadScheduler
for a queue and performing these Handle
tasks. http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler(v=vs.110).aspx
EDIT:
I would have a broadcaster class, as shown below, that knows when the operation is complete, and adds the finished event.
public class EventBroadcaster { public event EventHandler SomeEventOccured; public async void DoLongRunningOperationAndRaiseFinishedEvent() { var waitingTask = Task.Delay(TimeSpan.FromSeconds(2)); await waitingTask.ContinueWith(t => RaiseSomeEventOccured(), CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Current); } private void RaiseSomeEventOccured() { EventHandler handler = SomeEventOccured; if (handler != null) handler(this, EventArgs.Empty); } }
and then EventListener
public class EventListner { private readonly string _id; public EventListner(string id) { _id = id; } public void ListenTo(EventBroadcaster broadcaster) { broadcaster.SomeEventOccured += OnSomeEventOccured; } private async void OnSomeEventOccured(object sender, EventArgs eventArgs) { var currentTime = DateTime.Now; Console.WriteLine("EventListner {0} received at {1}", _id, currentTime.ToString("dd-MM-yyyy HH:mm:ss.fffffff"));
then it will be Program.cs for testing
public static class Program { public static void Main(string[] args) { var broadcaster = new EventBroadcaster(); var listners = new List<EventListner>(); for (int i = 1; i < 10; i++) { var listner = new EventListner(i.ToString(CultureInfo.InvariantCulture)); listner.ListenTo(broadcaster); listners.Add(listner); } broadcaster.DoLongRunningOperationAndRaiseFinishedEvent(); Console.WriteLine("Waiting for operation to complete"); Console.ReadLine(); } }
In this example, handler delegates are run one after another in the order in which they are signed.
Now change the code in Broadcaster to something like below Note. I changed the method signature from EventHandler
to Action
for coding convenience.
private void RaiseSomeEventOccured() { Action handler = SomeEventOccured; if (handler != null) { var parallelOption = new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }; Parallel.Invoke(parallelOption, Array.ConvertAll(handler.GetInvocationList(), ConvertToAction)); handler(); } } private Action ConvertToAction(Delegate del) { return (Action)del; }
Now you will see that events are triggered randomly.
I got better performance using option 1.
Note: always with TPL
and Parallel
programming, you need to make sure that there is an advantage before going for it.