Could somebody describe how should looks like class Worker with two events which triggers after some action is happened.
I have class Worker with one method ExecuteAsync. Inside this method I'm executing method i.e. DoStuff(). After that I want execute events. Event one and event two has different logic and have independent arguments which should be passed.
What goals I want to achieve.
I want to mock those events and test Worker without side effects.
Class Worker and events is SRP classes.
I can easily inject another realization of events without breaking my code.
I'm not completely understand this thing:
How should look's like realisation with injecting "body" of events.
Could I execute one event but inject inside it file search logic and sending http logic?
public class Worker
{
public event EventHandler<FileFoundArgs> FileFound;
public event EventHandler<SendHttpArgs> SendHttp;
public async Task ExecuteAsync()
{
DoStuff();
FileFound?.Invoke(this, new FileFoundArgs(file));
SendHttp?.Invoke(this, new SendHttpArgs(file));
}
}
Related
I have an application architecture like this:
When UDP servers inside the UDP service receive different types of messages it publishes Prism events to managers. Those UDP servers have their own threads so when the events published they sometimes cause multithreading issues inside the managers.
To prevent that I want to create an event handler and queue inside the subscribing managers. When subscriber receives an event, its only job is to try to Enqueue the event payload to ConcurrentQueue inside the managers and return (I think this is called store and forward). Then I will have a worker that will read this queue and send the event parameters to related methods.
Every manager will have its own event queue, event handler and worker.
My "event queue":
But when I try to implement this I couldn't get past some issues:
1- When you subscribe to an event, public class TestEvent1 : PubSubEvent<Class1>, like this, GetEvent<TestEvent1>().Subscribe(OnTestEvent1), callback method(OnTestEvent1) must have same type of parameters of the event, in this case Class1, OnTestEvent1(Class1 class1). I need a type to store every received data and event type.
How can I use the same callback method for all my events inside the subscriber manager that have different types?
Example:
// Events
public class TestEvent1 : PubSubEvent<Class1>
{
}
public class TestEvent2 : PubSubEvent<Class2>
{
}
public class TestEvent3 : PubSubEvent<List<Class3>>
{
}
// Subscriptions
_eventAggregator.GetEvent<TestEvent1>().Subscribe(EventHandler, true);
_eventAggregator.GetEvent<TestEvent2>().Subscribe(EventHandler, true);
_eventAggregator.GetEvent<TestEvent3>().Subscribe(EventHandler, true);
// Callback
private void EventHandler("What's inside here?")
{
_eventQueue.Enqueue(payload);
return;
}
2- Since I want to store all of the received events for a manager inside a single queue, the same type problem applies to this too, what should be my T when creating ConcurrentQueue?
3- Is this viable? Are there any other approaches, patterns(I found mediator but I didn't research it deeply enough) that I can use like this?
What I tried:
1- I tried to use object or dynamic type but then I will lose compile-time security.
2- I thought of creating an interface and implementing it on all of my custom classes so I can use it for general type but what to do about events with built-in types?
PS: I had another question about this but I felt like I didn't explain myself clearly so I tried my best again.
How can I use the same callback method for all my events inside the subscriber manager that have different types?
You don't. The event aggregator isn't designed that way. The type of the event is used to distinguish subscriptions and to distribute the event to the subscribers that actually want it, so you can only ever subscribe to an individual event type.
As said before, you shouldn't be using the event aggregator here at all, because there are much better tools for what you're trying to achieve.
Since I want to store all of the received events for a manager inside a single queue
If, for example, the manager was an dataflow ActionBlock it would come with a fully functional queue preinstalled.
all:
This issue comes from my currently working C# project. In solution, it includes three projects, one is UI project, another is interface project, the third is component project. The basic idea of my solution is UI project can dynamic load the component DLL which inherit interface defined in interface project. And in interface project, I defined two classes, one is a interface which is used by UI project to dynamic load DLL, and this interface defines all exposure entities in component object. And besides this interface, there's another abstract component core class which inherit public interface, and it includes all common operations in actual component object. I draw a plot following to describe my explanation before.
"UI Class ---> Interface <--- Abstract Component Core <--- Actual Component"
And in my design, I use C# BackgroundWorker in abstract component core object. And BackgroundWorker contains two event ProgressChanged and RunWorkerCompleted. In my design idea, these two events should be registered by UI Class. For example, UI class can register its operation when component's BackgroundWorker's progress changing or operation finishing. And another thing is that I don't want to expose BackgroundWorker object in Component Core to UI class, so the BackgroundWorker object is defined in abstract component core, not in interface. So in my raw design, I create two events in interface which accepts same event handler as BackgroundWorker's two events. As following:
event EventHandler<ProgressChangedEventArgs> ProcessChanged;
event EventHandler<RunWorkerCompletedEventArgs> RunWorkerCompleted;
And in later some places, I will assign these two event handlers to BackgroundWorker's actual events. Code as following:
mBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler ( this.ProcessChanged );
mBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler ( this.RunWorkerCompleted );
But I don't like this design. Because the user of componet (here is UI class) assign its event handler to component's event, and it real operation, component will add (+=) this event handler to BackgroundWorker's event handler. So this cause BackgroundWorker will have several same event handler if UI running again and again. The idea situation for me is that: 1-BackgroundWorker's event only can contain one event handler; 2-When user assign event handler to component core's own event, then it can transfer this event handler to BackgroundWorker's event at the same time;
Anyone can give me some workable design idea? Thanks!
I find a solution to solve my problem. I can use add and remove keyword to customer define my event accessor in my component core class. Code as following:
public virtual event ProgressChangedEventHandler ProcessChanged
{
add
{
lock ( mEventLock ) { mBackgroundWorker.ProgressChanged += value; }
}
remove
{
lock ( mEventLock ) { mBackgroundWorker.ProgressChanged -= value;}
}
}
So this can solve my problem. User assigning to component core event can immediately assign the event to BackgroundWorker's related event. This is what I want. So in my above question, two parts of code can integrate into one part of code.
I have a class ChatManager, which has a ChatServer and a ChatClient(WCF) class inside of them.
I want my controller which instantiates the ChatManager to be able to subscribe to the UserConnected, UserDisconnected and MessageReceived events that are on the ChatClient.
What is the most elegant and logical way to do this? Is it silly for me to define the events in the ChatClient like I have, and then redefine the events in the ChatManager solely to pass the events up to the Controller without it having to deal with or know about the ChatClient? The ChatManager would subscribe to the events of the ChatClient, and then fire off its own events which the ChatController would be listening to.
I know WPF has the concept of bubbling up of events, but I don't know if that is for this type of scenario, since nothing is part of a user interface.
I'd start by questioning whether both ChatManager and ChatController can both justify their own existence. Generally whenever you find yourself creating a "Manager" class, it really isn't necessary, especially if part of what it is doing consists of merely relaying messages.
Controller classes can struggle against SRP since their "responsibility" is quite broad. In cases where you want to delegate responsibility for certain behaviour then leave the responsibility for the ChatClient with the controller, and initialize a subordinate controller with the ChatClient (through a contract interface) so that it can interact with the client as needed. Just make sure that when you start registering for events that you de-register those events before discarding subordinates or the client, otherwise you'll be looking at managed memory leaks.
It is not bubbling events you are looking for. You can easily subscribe to these events by calling an instance of the child class in your parent (ChatManager) and subscribing to the Events like so :
chatManager.UserConnected += (param1, param2) => {
//your code here
};
Unless you have a need for an event to only conditionally reach the things that would subscribe to it (or to be processed sequentially by multiple handlers), "bubbling" isn't really something you should need. Using an event aggregator would probably be the best way to go.
I need to initialize few objects, it can take a while so I want to do it in some background thread. I also want to display progressBar showing what is the progress of initialization.
What is the most elegant way to do it?
I was thinking about an interface:
interface ILoadable
{
int Progress { get; }
event EventHandler Loaded;
}
Why not just use a BackgroundWorker directly? It provides events for DoWork, ProgressChanged, and RunWorkerCompleted.
The advantage of this (or a thin wrapper over this) is that you automatically get the threading handled for you, properly, and it's very well tested.
If you want to make a wrapper around this, I'd actually recommend making yourself an abstract class that encapsulates the BackgroundWorker, and lets you provide Action delegates for the run operation.
I have a class that handles events created by multiple member objects. Events from these objects spawn worker threads for the event, so that the various event handlers in my class are running on different threads (one is a serial handler, one is a timer event, etc.) I'm looking for a simple way to make my code thread-safe, preferably by forcing the event handlers to run on my object's thread.
If this were a Forms UI object, I could take advantage of its implementation of the ISynchronizeInvoke interface, and make calls to InvokeRequired, Invoke, etc. In WPF I could use a Dispatcher object. But my class needs to run *independently of any UI code.
Here's a simplified example of what I have:
public class MyClass
{
private SomeObject object1;
private AnotherObject object2;
public MyClass()
{
object1 = new SomeObject();
object2 = new AnotherObject();
object1.AThreadedEvent += ThreadedEventHandler1;
object2.AnotherThreadedEvent += ThreadedEventHandler2;
}
// This runs in its own thread!
private void ThreadedEventHandler1()
{
// DO STUFF HERE
}
// This runs in its own thread!
private void ThreadedEventHandler2()
{
// DO STUFF HERE
}
}
Because both event handlers access the same objects in the parent class (including each-other!), it would be awesome if there were a simple way to force the event handlers to run in the creating object's thread.
I've toyed with the idea of having my class implement the ISynchronizeInvoke interface, but it appears that doing so can get pretty complicated. Before I jump down that rabbit hole, I thought I'd ping the experts to see if there is a more simple solution.
Thoughts?
EDIT:
Part of the reason I want to run the event handlers in the parent object's thread is because the parent object has it's *own events that are triggered based on the events sent by its member objects. I'd like any threading functionality to be hidden by this class, so that code that uses the class doesn't have to worry about thread-related issues (ie. locks and so on). Simply locking shared data won't do the job, because I *still need to trigger events from within the threaded event handlers.
The ideea of invoking on another thread is hand to hand with having a while loop that from time to time it checks whether there is an "outside" message to be processed. For UI, there is the windows loop that does that. For an external thread, you must write manually a loop. Imagine a situation without a loop and that you have a relative long running thread right ? and sudently you want to interrupt this thread to invoke your message and resume what it was doing ON THE SAME shared stack memory. This interruption would destroy your stack. This is simply NOT possible. The other possibility is to use a synchronization mechanism such as ManualResetEvent and just wait for a signal (a signal that comes outside your thread). So, to resume, in order to process a message from another thread, you basically have only two options:
1) You have a while loop, eventually using a little sleep (to give some time / ticks to other threads to do their job)
while (true) {
Thread.Sleep (5);
if (someMessageArrived) { ... }
}
2) You just wait for a message implementing somehow the producer / consummer architecture:
On listening thread:
aManualResetEvent.WaitOne ();
On the "producer" thread:
aManualResetEvent.Set ();
There are advanced classes in .NET framework that might help such as BlockingCollection.
Hope this helps
Assumming, that your class runs in its own thread that the only logic is to execute the incomming calls from other threads, this would be the solution:
(comments inside)
public class MyClass
{
private SomeObject object1;
private AnotherObject object2;
public MyClass()
{
object1 = new SomeObject();
object2 = new AnotherObject();
object1.AThreadedEvent += ThreadedEventHandler1;
object2.AnotherThreadedEvent += ThreadedEventHandler2;
}
// This runs in its own thread!
// Only add the real function call to the queue
public void ThreadedEventHandler1()
{
tasks.Add(ThreadedEventHandler1_really);
}
private void ThreadedEventHandler1_really()
{
// DO STUFF HERE
}
// This runs in its own thread!
// Only add the real function call to the queue
public void ThreadedEventHandler2()
{
tasks.Add(ThreadedEventHandler2_really);
}
// here is the actual logic of your function
private void ThreadedEventHandler2_really()
{
// DO STUFF HERE
}
// the queue of the tasks
BlockingCollection<Action> tasks = new BlockingCollection<Action>();
// this method never returns, it is blocked forever
// and the only purpose of i is to do the functions calls when they added to the queue
// it is done in the thread of this instance
public void StartConsume()
{
foreach (Action action in tasks.GetConsumingEnumerable())
{
// add logic before call
action();
// add logic after call
}
}
}
The solution based on that the caller threads tat calls the functions: ThreadedEventHandler1 and ThreadedEventHandler2, actually add the real call to the queue and emediately continue with their run.
From the other hand, StartConsume function iterates the queue and makes the calls of the added method calls. If you want to add another logic before and after call, you can add it in this function.
Hope it helped to achieve your goal.
Without completely understanding the rational behind your design. I can say that the problem you are trying to solve was solved many times before.
I will assume your main object is like a service which expects calls (in this case events) from itself and other services (the sub objects). If you would think about it in terms of services (which you arguably should) WCF solves that problem for you doing all the heavy lifting #Rami suggested.
You define the main service with the following behavior:
Instance Context Mode - Single
Concurrency Mode - Single
More about these here.
And every event handler would call that main service notifying it about the event.
I am pretty sure you would not go that far and implement every class as a service, but thought it is worth offering anyway as an option.
OK, based on all of your feedback (thanks!) I have a solution to my problem. The short answer: what I wanted to do isn't possible.
Here are more details for those who asked. I'm writing a DLL that manages a device attached to a serial port. This includes basic serial port COM (packet TX and RX, including parsing), and higher-level protocol behavior (TX, Ack, retry on timeout, etc.) The serial port event handlers provided by .NET are obviously asynchronous, as are the System.Timers.Timer objects that I use to handle timeouts, etc.
I am building the code around an MVVM architecture, so that my UI doesn't have any logic in it whatsoever. Hence my need to avoid exploiting Dispatcher or Invoke functionality provided by the UI.
What I was looking for was a way to handle asynchronous events within my DLL in the same simple manner provided by WinForms and WPF. But as has been pointed out, and as I learned when digging deeper, what you are *really doing when you call BeginInvoke or a Dispatcher is pushing something onto a queue, to be consumed later by a different thread polling the queue. Outside the context of a UI, no such polling architecture exists.
SO. My options are to lock the shared objects in my class to make it thread safe, or to implement my own polling architecture within another thread (to avoid blocking the program that uses the DLL) that emulates what the UI code already does.
In either case, the UI code will still need to use its Invoke or equivalent tools when handling events from the DLL class. I suppose that's OK.