Callback-way to work with Events - c#

I do not understand some things of work with callbacks.
I have some third-party code wich connect,disconnect,subscribe to values from some system.
So, the example is:
class Subscriber:ISubscriber
{
public void OnConnected()
{
}
public void OnDisconnected()
{
}
}
Then, it uses:
var subscriber=new Subscriber();
_someSystemObj.CreateConnection(subscriber); //i do not understand how it works there
And then _someSystemObj calls OnConnected or OnDisconnected.
So, i have two questions:
1.How can _someSystemObj calls OnConnected method (it use Observer pattern or may be it use it other way. Can you describe it? Get some schematic code to understand how it may work.
If i want to do many steps when OnDisconnect happens: should i throw some public event to other classes? I mean than i can not do Disconnection in this OnDisconnect method (i have to do some steps in other part of my code and at old version of this API i just rethrow event OnDisconnect on top of my program and then handle it.)
This old version of code looks like:
_server.OnDisconnect+=OnDisconnectHandler;
void OnDisconnectHandler(..)
{
if(OnReconnect!=null)//some public event
OnReconnect(e);// throw on top of my program and then handle it there
}
At new version of API i try to solve it by add public event and when OnDisconnect happens throw it on top:
class Subscriber:ISubscriber
{
public event EventHandler<EventArgs> OnDisconnectedHappens;
public void OnConnected()
{
}
public void OnDisconnected()
{
if(OnDisconnectedHappens!=null)
OnDisconnectedHappens(this,e);//thow on top
}
}
And in some place:
_subscriber.OnDisconnectHappens+=OnDisconnectHandler; //and do my work
Or, may be it not right way. May be i should do something else?
Please,can you give me a some link, that i can learn about this model of event callbacks?
Or, may be i do it correctly?

How can _someSystemObj call OnConnected method?
Well, you gave it a subscriber when you called CreateConnection(subscriber). It's probably implemented something like this:
private readonly List<ISubscriber> _subscribers = new List<ISubscriber>();
public void CreateConnection(ISubscriber subscriber)
{
_subscribers.Add(subscriber);
}
private void OnConnectedNotifySubscribers()
{
foreach (ISubscriber subscriber in _subscribers)
{
subscriber.OnConnected();
}
}
If I want to do many steps when OnDisconnect happens, should I raise some public event to other classes?
That is a valid option, but it can get difficult to debug when there are too many layers in an event chain. Another option is to increase the capability of your Subscriber class so that it can do everything necessary to handle the subscription events.
class EmpoweredSubscriber : ISubscriber
{
private readonly DisconnectWorker _worker;
private readonly DisconnectHelper _helper;
public EmpoweredSubscriber(DisconnectWorker worker, DisconnectHelper helper)
{
_worker = worker;
_helper = helper;
}
public void OnConnected()
{
}
public void OnDisconnected()
{
_worker.DoWork();
_helper.DoHelp();
// more...
}
}

Related

Listen for event and invoke callback, based on specification?

I am currently building out a custom task manager and I'm wondering if it's possible to tell the task manager to listen for a specific event (OnSomething below), and then invoke a callback method when the task raises that event. However, mentally I can't see how it's possible to listen for an event that doesn't exist at the base class level. For example, I have a base class that contains basic information about the task called CustomTask:
public abstract class CustomTask {
public bool IsRunning { get; private set; } = false;
public void Start() {
IsRunning = true;
DoSomething();
IsRunning = false;
}
protected abstract void DoSomething();
}
For the sake of SO readers, I've simplified the definition, but you get the gist of it. It contains basic details, a few methods for starting and canceling, provides basic state management (simplified IsRunning here), etc.
I then have custom tasks that derive from CustomTask, in this case, let's focus on a sample task called CustomTaskA. It contains a definition for an event called OnSomething, which someone, somewhere may want to listen for:
public sealed class CustomTaskA : CustomTask {
protected override void DoSomething() => RaiseOnSomething(this, new EventArgs());
public event EventHandler<EventArgs> OnSomething;
private void RaiseOnSomething(object sender, EventArgs e) => OnSomething?.Invoke(sender, e);
}
Now, the CustomTaskManager registers tasks, tracks them via Guid, manages them and more, but for simplicity:
public sealed class CustomTaskManager {
// Singleton setup.
private static CustomTaskManager _instance = new CustomTaskManager();
public static CustomTaskManager Instance {
get {
// Simplified for SO.
if (_instance == null)
_instance = new CustomTaskManager();
return;
}
}
// Collection of tasks.
private Dictionary<Guid, CustomTask> _tasks = new Dictionary<Guid, CustomTask>();
// Register and start a task.
public bool TryRegisterAndStartTask(CustomTask task, out Guid taskId) {
taskId = Guid.Empty;
try {
// Register task.
taskId = Guid.NewGuid();
_tasks.Add(taskId, task);
// Listen for events.
// Start task.
task.Start();
} catch (Exception e) {
// Log exception.
}
return false;
}
}
When registering and starting a task, I'd like to tell the task manager I want to listen for OnSomething, and if OnSomething is invoked, I want the task manager to call a method OnSomethingWasRaised. For example:
TaskManager.Instance.TryRegisterAndStartTask(task, out Guid taskId, task.OnSomething, OnSomethingWasRaised);
private static void OnSomethingWasRaised(object sender, EventArgs e) {
Console.WriteLine("Woohoo!");
}
I know the specifying and invoking a callback method is entirely possible, and listening for events is plausible with reflection.
Is there a way (with or without using reflection) to listen for a specified event defined on a derived object and then invoke a specified callback method?
NOTE: Please excuse any syntactical errors as I hand-typed the snippets to keep them minimal.
Problem with (proposed) approach like this:
TryRegisterAndStartTask(task, out Guid taskId, task.OnSomething, OnSomethingWasRaised);
is that you cannot pass event as argument, or store it in variable, because event is just a set of two methods (add and remove), just like property is a set of two methods get and set.
You can of course change event to "raw" delegate:
public EventHandler<EventArgs> OnSomething;
This one you can pass by reference:
public bool TryRegisterAndStartTask(CustomTask task, ref EventHandler<EventArgs> del, EventHandler<EventArgs> sub, out Guid taskId) {
taskId = Guid.Empty;
// subscribe
del += sub;
...
}
CustomTaskManager.Instance.TryRegisterAndStartTask(task, ref task.OnSomething, OnSomethingWasRaised, out var taskId);
But that's usually not a good idea, since you are losing private scope of events - with events one can only add\remove delegates, with raw delegate anyone can do anything, like invoking or setting to null.
If regular event stays - that means reflection is the only way to achieve your goal, and even worse - you'll have to reference to the event you want to subscribe to by string name, not by an actual reference, though you can use nameof(task.OnSomething). Then, you are losing compile time validation of subscription delegate type. Say you want to subscribe to event Action Something but passing Func<string> delegate there. It will compile fine with reflection approach, and fail only at runtime.
Still if you insist that will look something like this:
public bool TryRegisterAndStartTask(CustomTask task, string eventName, Delegate sub, out Guid taskId) {
taskId = Guid.Empty;
// subscribe
var ev = task.GetType().GetEvent(eventName, BindingFlags.Public | BindingFlags.Instance);
var addMethod = ev.GetAddMethod(); // this can be null or private by the way
addMethod.Invoke(task, new [] {sub});
...
}
And called like this:
var task = new CustomTaskA();
EventHandler<EventArgs> handler = OnSomethingWasRaised;
CustomTaskManager.Instance.TryRegisterAndStartTask(task, nameof(task.OnSomething), handler, out var taskId);
Ugly, unsafe, and not worth it in your scenario, in my opinion.

All classes with particular Interface should be notify by event

How,does one should call an event declared by interface so that all the classes that has implemented that interface get notified??
For example in structure like this,
public delegate void myDel(int value);
interface IEventCaller{
event myDel myDelEventCall;
}
public Class One : IEventCaller {
public event myDel myDelEventCall;
}
public Class Two : IEventCaller {
public event myDel myDelEventCall;
}
I want both class One and Two to get notify and act as event gets called, I am feeling somewhere I am going wrong direction , is it possible to do?
Actually what you want doesn't involve events. Events would be used by an object implementing IEventCaller to notify some object holding a reference to that object of some change. To invoke something on the object implementing IEventCaller would just require a method, for example Hello();
First, you need code that informs all the objects that implement this interface. To make that possible, you somewhere need to store a list of instances that want to get notified.
One solution would be to create a class that manages that list. Let's say like this
private static List<IEventCaller> eventCallers = new List<IEventCaller>();
public static void AddEventCaller(IEventCaller c)
{
eventCallers.Add(c);
}
public static void RemoveEventCaller(IEventCaller c)
{
eventCallers.Remove(c);
}
public static IEventCaller[] EventCallers
{
get { return eventCallers.ToArray() }
}
Of course this code needs to be thread safe, etc. I'd put all this into a singleton to be globally available.
Then, all objects that implement IEventCallers need to register/unregister accordingly. Thus, I'd also have them Implement IDisposable so that in the constructor you can do
public EventCallable()
{
Singleton.Instance.AddEventCaller(this);
}
and in the Dispose method you can do this:
public void Dispose(bool disposing)
{
Singleton.Instance.RemoveEventCaller(this);
}
Now the code that should notify every instance could just do this:
public void NotifyAll()
{
foreach (IEventCaller caller in Singleton.Instance.EventCallers)
caller.Hello();
}
I think you might be looking at this the other one around.
With events, you want to have an object which is the publisher, which is responsible for publishing the event and saying "hey guys, something just occurred and you should know about it", and you have your subscribers, which are the guys who say "Yo dawg, let me know when that thing occurs, so i can act on it".
What you can do is have the object which is responsible for the event occurring implement your interface:
public class Publisher : IEventCaller
{
public event MyDel MyDeleteEvent;
public void OnDeleteOccured()
{
var myDeleteEvent = MyDeleteEvent;
if (myDeleteEvent != null)
{
MyDeleteEvent(1);
}
}
}
And then have your One and Two objects register to that event occurring, where they pass a method which signature matches the delegate type of MyDel:
public class SubscriberOne
{
public void OnSomethingOccured(int value)
{
Console.WriteLine(value);
}
}
public class SubscriberTwo
{
public void OnSomethingOccured(int value)
{
Console.WriteLine(value);
}
}
And the registration goes:
void Main()
{
var publisher = new Publisher();
var subscriberOne = new SubscriberOne();
var subscriberTwo = new SubscriberTwo();
publisher.MyDeleteEvent += subscriberOne.OnSomethingOccured;
publisher.MyDeleteEvent += subscriberTwo.OnSomethingOccured;
}

Event handler for rasing notifications between classes is always null

in a service class I have a method at which end I want to raise an event that can be listened by other two services.
This is how I'm trying to do it. But my problem is that the null check for the handler is always true.
Inside the IProfileService file I define the delegate and the actual interface
public delegate void PersonDetailsUpdated(Person person, bool personDetailsWereUpdated);
public interface IProfileService
{
void UpdateContactDetails(Person person);
event PersonDetailsUpdated PersonDetailsUpdatedEvent;
}
And this is the instance of that interface
public class ProfileService : IProfileService
{
// ... Dealing with dependency injection
public event PersonDetailsUpdated PersonDetailsUpdatedEvent;
public void UpdateContactDetails(Person person)
{
//... Doing stuff
//We raise an event
var handler = PersonDetailsUpdatedEvent;
if (handler != null)
{
handler(person, personDetailsWereUpdated);
}
}
}
}
Now in the other two services I do this (I only put the code of one of them)
internal class CustomerSmsService : ICustomerSmsService
{
private readonly IPersonDAL _personDal;
// ... Other dependencies...
public CustomerSmsService(IPersonDAL personDal, /* ... the other dependencies */ IProfileService profileService)
{
_personDal = personDal;
//... Again the other dependencies
profileService.PersonDetailsUpdatedEvent += (SendPhoneValidationCode);
}
//... Other methods
// What I understand is the so called Listener
public void SendPhoneValidationCode(Person person, bool personDetailsWereUpdated)
{
//Stuff
}
}
Maybe the answer is obvious but haven't worked with events before and I'm finding it impossible to figure out or to find an example that is clear enough for me although there's quite a bunch of them. But they seem to have followed another approach.
Thanks

Making a generic scheduler of Action<T> with Reactive Extensions

I'm experimenting a lot with Reactive Extensions and right now I'm trying to make a system in which I can queue procedures and execute them in whatever fashion I want while being able to send notifications to subscribers.
I currently have my database access encapsulated within a UserAccess class that exposes the method to add a user. In that method I would like to queue an action that adds a user to the database. So I made a JobProcessor of T class that exposes a method QueueJob(Action) and have my User implement this class. My problem is I can't see how to call the Action from within the OnNext method of the Observable because the action takes a User parameter.
My angle of attack must be wrong and there must be a problem with my grasp of the design. For example I know I should somehow pass my user to the QueueJob procedure but I don't know how to do it in a clean way.
public class UserAccess : JobProcessor<User>
{
public void AddUser(User user)
{
QueueJob(usr =>
{
using (var db = new CenterPlaceModelContainer())
{
db.Users.Add(usr);
}
});
[...]
public abstract class JobProcessor<T>
{
// Either Subject<T> or Subject<Action<T>>
private Subject<Action<T>> JobSubject = new Subject<Action<T>>();
public JobProcessor()
{
JobSubject
/* Insert Rx Operators Here */
.Subscribe(OnJobNext, OnJobError, OnJobComplete);
}
private void OnJobNext(Action<T> action)
{
// ???
}
private void OnJobError(Exception exception)
{
}
private void OnJobComplete()
{
}
public void QueueJob(Action<T> action)
{
JobSubject.OnNext(action);
}
}
Edit 1 :
I tried to change the signature of QueueJob to
QueueJob(T entity, Action<T> action)
Now I can do
QueueJob(user, usr => { ... } );
But it does not seem very intuitive. I haven't seen many frameworks in which you pass both the entity and the action. With that I might as well not need the JobProcessor.
Edit 2 :
I changed my JobProcessor's subject type to Subject, removing the T altogether. Since there was no need to include the User in the procedure since I can refer to it externally. The only problem now is if the User I pass to the QueueJob's action changes between the actual time of the Action execution, the user will have the modified information. Undesirable but I guess I will continue looking for a solution.
My code is now (used Buffer for sample) :
public abstract class JobProcessor
{
public Subject<Action> JobSubject = new Subject<Action>();
public JobProcessor()
{
JobSubject
.Buffer(3)
.Subscribe(OnJobNext, OnJobError, OnJobComplete);
}
private void OnJobNext(IList<Action> actionsList)
{
foreach (var element in actionsList)
{
element();
}
}
private void OnJobError(Exception exception)
{
}
private void OnJobComplete()
{
}
public void QueueJob(Action action)
{
JobSubject.OnNext(action);
}
}
First off, I have to agree with Lee and NSGaga that you probably don't want to do it this way - there are other patterns for a Producer/Consumer queue that are far more aligned with what (I think) you are trying to accomplish here.
That said, since I can never resist a challenge...with some minor tweaks, you can remove your immediate problem of "What do I pass into the action?" by just capturing the user parameter passed in and making it a straight-up Action - Here's your code with some modifications:
public class UserAccess : JobProcessor
{
public void AddUser(User user)
{
QueueJob(() =>
{
using (var db = new CenterPlaceModelContainer())
{
db.Users.Add(user);
}
});
[...]
public abstract class JobProcessor
{
// Subject<Action>
private Subject<Action> JobSubject = new Subject<Action>();
public JobProcessor()
{
JobSubject
/* Insert Rx Operators Here */
.Subscribe(OnJobNext, OnJobError, OnJobComplete);
}
private void OnJobNext(Action action)
{
// Log something saying "Yo, I'm executing an action" here?
action();
}
private void OnJobError(Exception exception)
{
// Log something saying "Yo, something broke" here?
}
private void OnJobComplete()
{
// Log something saying "Yo, we shut down" here?
}
public void QueueJob(Action action)
{
JobSubject.OnNext(action);
}
}
I'm not frankly sure what is your `goal' here - but I think you got it backwards a bit...
Normally subject is exposed via property like
IObservable<Action<T>> NewJob {get{return _subject;}}
...or something. (Subject becomes observable - subject is dual in nature - and why it's specific - and a bit controversial - but good for playing around etc.)
And you just call OnNext from inside the class - like you did.
But you do not normally subscribe to the observable yourself
...you let the outside users do that by 'hooking' into your property - and defining subscribe - which gets them new items as they arrive.
This is simplified of course, there are many cases and many uses but this might help I hope
My initial reaction is that IObservable is normally best suited for creating sequences of immutable data structures, not method-pointers/delegates/actions.
Next I would suggest that if you are trying to 'schedule' actions to be processed in a queue fashion, then the IScheduler implementations in Rx seem like a perfect fit!
Alternatively if you are actually trying to create a ProduceConsumer Queue, then I dont think Rx is actually the best fit for this. i.e. if you are putting a heap of messages into a queue and then having some consumers reading these messages off and processing them, I would look to a different framework.
I finalized my design and found something that I like. Here is the code if anyone else needs it.
public class JobProcessor<T> : IDisposable where T : new()
{
private ISubject<Action<T>> jobsProcessor = new Subject<Action<T>>();
private IDisposable disposer;
private T _jobProvider = new T();
public JobProcessor(Func<ISubject<Action<T>>, IObservable<IEnumerable<Action<T>>>> initializer)
{
Console.WriteLine("Entering JobProcessor Constructor");
disposer = initializer(jobsProcessor)
.Subscribe(OnJobsNext, OnJobsError, OnJobsComplete);
Console.WriteLine("Leaving JobProcessor Constructor");
}
private void OnJobsNext(IEnumerable<Action<T>> actions)
{
Debug.WriteLine("Entering OnJobsNext");
foreach (var action in actions)
{
action(_jobProvider);
}
Debug.WriteLine("Leaving OnJobsNext");
}
private void OnJobsError(Exception ex)
{
Debug.WriteLine("Entering OnJobsError");
Debug.WriteLine(ex.Message);
Debug.WriteLine("Leaving OnJobsError");
}
private void OnJobsComplete()
{
Debug.WriteLine("Entering OnJobsComplete");
Debug.WriteLine("Leaving OnJobsComplete");
}
public void QueueJob(Action<T> action)
{
Debug.WriteLine("Entering QueueJobs");
jobsProcessor.OnNext(action);
Debug.WriteLine("Leaving QueueJobs");
}
public void Dispose()
{
disposer.Dispose();
}
}
I selected a generic make to support an architecture in layers where I could use the JobProcessor in a layer of concurrency where I could select how fast or slow my execution can be. The JobProcessor constructor takes a Func used to declare the Observable sequence somewhere else in the code and generate a processor that executes jobs an the order described by the sequence. The OnNext takes in an IEnumerable> to be able to support sequences like .Buffer(3) that returns a batch of actions at the same time. The downside to that is that when creating a sequence returning single actions at a time I need to do this
var x = new JobProcessor<DatabaseAccess<User>>(subject => subject.Select(action => action.Yield()));
The Yield() extension methof of T returns an enumerable of a single element. I found it here Passing a single item as IEnumerable<T>.

Command pattern and asynchronous operations handling in C#

I'd like to hear opinions on the best way to handle asynchronous operations with the Command pattern. Say we have the following example:
public class MyCommand
{
// Sets up receiver and does whatever stuff
public void Execute()
{
_myReceiver.DoSomething();
}
}
The problem is: MyCommand doesn't know whether MyReceiver.DoSomething() has async portions of code. If i wanted to push MyCommand into an undo stack after its execution, i couldn't guarantee that its receiver action has been fully executed, making it uncertain to know if MyCommand reached a state where undoing is possible or not.
I personally thought on the following solution:
Implement some sort of state control in Command
Include "BeginExecute" and "EndExecute" in Command
Include events in MyReceiver and make Command subscribe to them (that seems smelly to me)
To wrap things up, MyCommand would turn into:
public class MyCommand
{
public MyCommand(MyReceiver receiver)
{
_myReceiver = receiver;
_myReceiver.DoSomethingFinished += () => this.EndExecute();
}
public void BeginExecute()
{
this.EnterExecutionState();
_myReceiver.DoSomething();
}
public void EndExecute()
{
this.LeaveExecutionState();
}
// State handling related stuff
}
I now have the means to make sure the Command's receiver has finished executing whatever action and it's ready to be pushed into the undo stack. However, to event-spam every single Receiver class that contains async operations really bugs me.
I haven't found much about this topic in the Internet and would love to hear different approaches.
OBS: Make the Command manage all the asynchronous-related code isn't an option :).
I think you've got way too much going on in a single class. I would break it down like this:
// An immutable command, to be handled in-process.
// ICommand is a marker interface with no members.
public class DoSomething : ICommand
{
public readonly Id;
public DoSomething(Guid id)
{
Id = id;
}
}
// To be handled out-of-process.
[AsynchronousCommand]
public class DoSomethingThatTakesAReallyLongTime : ICommand
{
public readonly Id;
public DoSomethingThatTakesAReallyLongTime(Guid id)
{
Id = id;
}
}
// This guy could take any number of dependencies: ISomethingRepository, DbContext, etc.
// Doesn't matter, but it's probably gonna have dependencies.
public class DoSomethingHandler : IHandler<DoSomething>
{
public void Handle(DoSomething command) // IHandler<T>'s only member
{
// CRUD or call call a domain method
}
}
public class CommandService : ICommandService
{
public void Execute(params ICommand[] commands) // ICommandService's only member
{
foreach(var command in commands)
{
var handler = GetHandler(command); // Could use your IOC container.
if (HasAsyncAttribute())
new Action(() => handler.Handle(command)).BeginInvoke(null, null);
else
handler.Handle(command);
}
}
}
// Something that might consume these
public class SomethingController
{
private readonly ICommandService _commandService;
public SomethingController(ICommandService commandService)
{
_commandService = commandService;
}
[HttpPost]
public void DoSomething(Guid id)
{
_commandService.Execute(new DoSomething(id));
}
[HttpPost]
public void DoSomethingThatTakesAReallyLongTime(Guid id)
{
_commandService.Execute(new DoSomethingThatTakesAReallyLongTime(id));
}
}
The big advantage here is that you can distribute your commands to clients without explicitly dragging along all the dependencies that go with the handlers. The handlers should not be known to the client. All the client needs to know is that it sent a command, and all commands should be assumed to succeed.
Something like this?
public interface ICommand
{
void Execute();
event EventHandler Finished;
}
public class MyCommand : ICommand
{
public MyCommand(MyReceiver receiver)
{
_myReceiver = receiver;
_myReceiver.DoSomethingFinished += () => Finished(); // dont forget null check here.
}
public void Execute()
{
_myReceiver.DoSomething();
}
public event EventHandler Finished;
}
This way, user of this command can register to Finished event so it knows when command has finished its async behaviour and can act acordingly.
Or if you dont wan't to use event, then what about callback?
public class MyCommand : ICommand
{
public MyCommand(MyReceiver receiver)
{
_myReceiver = receiver;
}
public void Execute()
{
_myReceiver.DoSomething(() => Finished()); // dont forget null check here.
}
public event EventHandler Finished;
}
Either way, there simply need to be a way for MyReciever to notify its caller, that it finished. There is no way to bypass it.
First I would add to the name of the method Async to esplicitly signal to your Command class consumer that method executes in async way.
Second, I would add like parameter an Action<T> which will be called as method async call completes. So this method caller can be notified when async sction was terminated.
Edit
obj.DoSomethingAsync(... params, Action<T> onComplete)
If you are going to impose the requirement that all processing is completed before control returns to your Execute method, without modifying the calling code's behavior, you could modify the way that your actions execute.
First initialize all your asynchronous calls and block(wait) on the current thread for calls to return. I'm not sure what the nature of your asynchronous calls are, as in if they are in a Thread that you are aware of, or will be returned on an arbitrary thread, but you should be able to come up with some kind of thread synchronization for your problem.
Try using a Semaphore to block current thread(after calling your async methods), and release the semaphore when all your async methods have returned their response(s). This will have the effect of "re-synchronizing" your async calls.
You can use another synchronization method, but a Semaphore is simple enough to understand.

Categories