In c#,we normally make publisher like below:
public class Publisher
{
public event Action NotifySomethingEvent;
public void RaiseNotifySomethingEvent()
{
NotifySomething?.Invoke();
}
}
while the subscriber has define a method like this:
public void HandlerSomething()
{
Thread.Sleep(2000);
}
This subscriber would cause the publisher thread blocking.
Do there anyway to fix this issue?
By the way,the publisher BeginInvoke method will cause the subscriber execute time confuse,so is not in consideration.
the subscriber execute time confuse means:
class Program
{
static void Main(string[] args)
{
Publisher publisher = new Publisher();
SubScriber subscriber = new SubScriber();
publisher.NotifySomething += subscriber.HandlerSomething;
publisher.RaiseNotifySomething();
publisher.RaiseNotifySomething();
publisher.RaiseNotifySomething();
Console.ReadKey();
}
}
public class Publisher
{
public event Action NotifySomething;
public void RaiseNotifySomething()
{
NotifySomething?.Invoke();
}
}
public class SubScriber
{
int d = 0;
ReaderWriterLock locker = new ReaderWriterLock();
public void HandlerSomething()
{
d += 1;
Action<int> action = new Action<int>((t) =>
{
Thread.Sleep(100);
Console.WriteLine(t);
});
action.BeginInvoke(d, null, null);
}
}
}
the upper code expect result is : 1 2 3
but in fact it result is random,like 1,3,2 1,2,3 or 3,2,1
Apparently you do not want the subscribers to block the publishing thread but do want them to be executed in published order.
You could enqueue your published events and have another thread dequeue these events in order and wait for the subscribers to finish their job.
Building this can get dirty so I recommend you find a Pub-Sub library you feel comfortable with.
I would recommend the MassTransit project. It works async. It has queues. Additionally, you can put the concern of orchestrating the events into a workflow (called a Saga), whicht might come in handy when your project gets more complex.
I am unaware of the complexity of your project. MassTransit supports RabbitMQ but also in-memory as the transport layer. So it scales very well.
It is already done and is called ReactiveExtensions.
It implements IObservable interface which can publish events and you can subscribe to them. It also covers end of events and errors. Take a look.
There even is MVVM framework based on them called ReactiveUI
Related
I'm having an issue with updating WPF UI with the RX. Currently I have a class that has an event which is called within its functions. Event is subscribed from the UI thread and updates the UI like below :
SomeClass.cs
public partial class SomeClass
{
public delegate Task ProgressUpdate(string value);
public delegate Task BarUpdate(int value);
public event ProgressUpdate OnProgressUpdateList;
public event BarUpdate OnProgressUpdateBar;
public async Task DoSomething()
{
// execute code
<some code>
// update UI
if (OnProgressUpdateList != null)
{
OnProgressUpdateList(update);
}
}
}
And in MainWindow.xaml
var someClass = new SomeClass();
someClass.OnProgressUpdateList += Export_OnProgressUpdateList;
someClass.OnProgressUpdateBar += Export_OnProgressUpdateBar;
private async Task Export_OnProgressUpdateList(string text)
{
await Dispatcher.InvokeAsync(() =>
{
OutputLog.AppendText(text);
OutputLog.AppendText(Environment.NewLine);
OutputLog.ScrollToEnd();
});
}
This code works except the program processes huge number of files and I'm assuming this is why the UI becomes frozen very quickly (I see the updates being done in the first half a second). I searched for a way around this and I came into a solution to use RX for batching the UI calls. I've searched through several SO posts but I couldn't find an answer on how to correctly implements this (or convert C# events to RX observables) when I call those events from the class and subscribe to this event from outside that class. Can someone help me understand this?
I'm posting an answer to myself as I couldn't get one here and I finally figured it out so for anyone looking for that in the future - here you go:
public partial class SomeClass {
public Subject<string> outputLogSubject = new Subject<string>();
public IObservable<string> OutputLog => outputLogSubject.AsObservable();
//Add string for collection updating UI
outputLogSubject.OnNext(string);
//After finishing the work you can call outputLogSubject.OnCompleted() to stop buffering
outputLogSubject.OnCompleted();
}
It needs to be added in the class that will be calling the executing the work.
Below needs to be added in the UI thread after initialization and BEFORE processing work :
var buffer = someClass.OutputLog.Buffer(TimeSpan.FromMilliseconds(1000), 6);
var chunked = buffer.ObserveOnDispatcher(DispatcherPriority.Background);
var update = chunked.Subscribe(name =>
{
foreach (var item in name)
{
OutputLog.AppendText(item);
}
OutputLog.ScrollToEnd();
});
This allowed me to keep the UI responsive to the point of seeing the output log is real time
I am developing an WPF application and tried to design something event driven using Prism's Event Aggregator.
Currently I am trying to implement something like event queue for Prism events.
To do that I want to subscribe related events and pass them to same method but Event Aggregator wants those methods to have same signature with the event.
Example events:
public class TestEvent1 : PubSubEvent<Class1>
{
}
public class TestEvent2 : PubSubEvent<Class2>
{
}
public class TestEvent3 : PubSubEvent<List<Class3>>
{
}
public class TestEvent3 : PubSubEvent<string>
{
}
Subscriptions:
_eventAggregator.GetEvent<TestEvent1>().Subscribe(OnTestEvent1, true);
_eventAggregator.GetEvent<TestEvent2>().Subscribe(OnTestEvent2, true);
_eventAggregator.GetEvent<TestEvent3>().Subscribe(OnTestEvent3, true);
Example callback method:
private void OnTestEvent1(Class1 object1)
{
// do something
}
Since I only receive data when event published, I tried something like this to use as event payload type, but it doesn't look right:
// Payload
public interface IMessage
{
public object Data { get; set; }
public Type Datatype { get; set; }
public PubSubEvent EventType { get; set; }
}
// Events
public class TestEvent1 : PubSubEvent<IMessage>
{
}
public class TestEvent2 : PubSubEvent<IMessage>
{
}
public class TestEvent3 : PubSubEvent<IMessage>
{
}
// Subscriptions
_eventAggregator.GetEvent<TestEvent1>().Subscribe(EventHandler, true);
_eventAggregator.GetEvent<TestEvent2>().Subscribe(EventHandler, true);
_eventAggregator.GetEvent<TestEvent3>().Subscribe(EventHandler, true);
// Callback
private void EventHandler(IMessage payload)
{
// do something
}
Is this viable and how can I improve or change my "generic" payload?
Extra information:
In my scenario I have multiple UDP servers that periodically receives new data, deserialize it to objects and publish events.
Related "managers" subscribed to those events and get triggered when new data received.
My goal is try to implement an event queue like system in my event receiving classes so it will be easier to deal with multithreading issues.
Here are some diagrams that may help me explain myself better:
My architecture:
My "event queue"
This is more of a code-review question, isn't it?
I would very much prefer strong typing, though, and I wouldn't want to build a queue around the event aggregator, that will always be tedious because you never know when new event types show up. Instead, I'd build my own event aggregator with queueing built in (starting from the existing one).
Also, I'd look into dataflow, for example, because the basic working mode of the event aggregator (fire and forget, one sender, multiple or no receivers) doesn't seem to work well with queueing. If you queue at the sender-side, to you wait for one receiver or all? Do you queue when there are no receivers or do you discard then? If you queue at the receiver-side, why bother at all? The receiver can implement the queue on its own.
When you publish an event with a reference to an object, consider these potential problems:
Any listener will be dependent on the type/assembly of the event parameter.
The referenced object will be held for some time. For how long? You don't know.
The referenced object could have been altered/disposed.
Listeners might handle the referenced object on a different thread.
After dealing with PubSubEvent<T> for several years now, I believe there is only one suitable pattern that successfully handles all cases. Publish your event with a unique identifier, e.g. a Guid.
public class MyItemAddedEvent : PubSubEvent<Guid> {}
Then inject a provider wherever you listen for this event:
public class SomeListener
{
private readonly IMyItemProvider myItemProvider;
[ImportingConstructor]
public SomeListener(IEventAggregator eventAggregator,
IMyItemProvider myItemProvider)
{
this.myItemProvider = myItemProvider;
eventAggregator.GetEvent<MyItemAddedEvent>().Subscribe(OnMyItemAdded, true);
}
private void OnMyItemAdded(Guid id)
{
var myItem = myItemProvider.Get(id);
// Do stuff
}
}
Now it is the responsibility of the provider class to deliver a valid and up-to-date object given a unique id.
I have a class wich performs some data processing:
class Processor
{
public Processor() {
// Load lot of data
}
public string GetResult(string input) {
// ...
}
}
I need to implement a service wich exposes HTTP API to this class. I use Owin and Microsoft.AspNet.* libs to host HTTP Web API. For each request it creates a new thread to handle it, but I cannot instantiate Processor on every request as it takes enormous time to load some data in its constructor. Also I cannot reuse one instance from different threads as it was not designed to be thread safe. But I can instantiate several instances of Processor on service start, and then dispatch work among them. Say I allow up to 20 concurrent HTTP requests for my service. I create 20 instances of Processor and add Busy flag to the class:
class Processor
{
public bool Busy { get; set; }
// ...
}
I wrote Dispatcher class like this:
class Dispatcher
{
readonly Processor[] _processors;
readonly SemaphoreSlim _semaphore;
public Dispatcher(int maxProcessors)
{
_semaphore = new SemaphoreSlim(maxProcessors);
_processors = new Processor[maxProcessors];
// Instantiate Processors, etc...
}
public string GetResult(string input)
{
try
{
_semaphore.Wait(); // Surplus requests will wait here.
Processor processor;
lock (_processors)
{
// It is guaranteed that such processor exists if we entered the semaphore.
processor = _processors.First(p => !p.Busy);
processor.Busy = true;
}
var result = processor.GetResult(input);
processor.Busy = false;
return result;
}
finally
{
_semaphore.Release();
}
}
}
Then I can basically call it through Dispatcher in ApiController:
public class ServiceController : ApiController
{
static Dispatcher _dispatcher = new Dispatcher(20);
[Route("result")]
[HttpGet]
public string Result(string input)
{
return _dispatcher.GetResult(input);
}
}
Is it implemented correctly for my purpose?
I tested it and it works, but I wonder if I reinvented the wheel and .NET Framework has somewhat ready to use for my case, or if it could be implemented easier.
Basically in your class that is going to be run in the thread, create an event and event handler. The object that then spins up this task can register to that event. When it is raised by the task, (in this case you would raise the event when it is done) you can do something, ie. give it more work.
Create your events in the class that will be run in the child thread:
public event TaskCompleteEventHandler OnComplete;
public event TaskErrorEventHandler OnError;
Register to your events in the object that is spinning up the classes:
task.OnComplete += TaskComplete;
task.OnError += TaskComplete;
Create the function in the calling class that will handle the event:
public void TaskComplete()
{
//give the thread more work
}
I'm currently implementing a SignalR application to send a message to several clients when an external library I've written fire an event.
I want to attach a unique handler to my event for every instance of my hub, so I could send the messages only once when it is fired; but as SignalR instanciate many hubs on every request, I end up with more than one event handler attached every time. So my question is: what can I do to attach only once on my event ?
Here is my code:
public class MyHub : Hub
{
private static ExternalClass staticObject = new ExternalClass();
public MyHub()
{
staticObject.MyEvent += staticObject_MyEvent;
}
private void staticObject_MyEvent(object sender, EventArgs e)
{
//Some irrelevant code which send messages to clients
}
}
I know my question is pretty the same than this one and a lot of others, but I never found a satisfying anwser for multi-threaded or multi-instance environment - which is definitly my case.
Here is the code replacing my old event declaration in my library :
private bool isEventAlreadyRegistered = false;
private static readonly object verrou = new object();
private System.EventHandler myEvent = delegate { };
public event System.EventHandler MyEvent
{
add
{
if(!isEventAlreadyRegistered)
{
lock(verrou)
{
//Double check as multiple add can be made simultaneously
if(!isEventAlreadyRegistered)
{
isEventAlreadyRegistered = true;
myEvent += value;
}
}
}
}
remove
{
myEvent -= value;
}
}
It works magnificently. My only doubt was about the performances with the lock; but as it is used only on the first call, it's negligible.
Of course, this solution only works when you have access to the source code of your event.
Hubs live in transient life. Meaning it will be created for each type of transaction (connected, on client message, dissconnected etc).
Never, ever have anything else then SignalR logic in the hub. Move your code somewhere else and invoke the client method when you want to upate. Or use a library that already have abstracted that for your. For example this library (I'm the author)
https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/wiki
Live demo:
http://malmgrens.org/signalR/
We have a class which manages many queues that store data. I want a user to get notified when new data is added to each of these queues. I'd like to use the observer pattern using delegate and events. Normally for a single event and source, we'd do:
public delegate void NewDataAddedDelegate();
public event NewDataAddedDelegate NewDataAdded;
and for the observer:
qManager.NewDataAdded += new qManager.NewDataAddedDelegate(getNewDataFunc);
But in this case, we have, say, 10 queues, each of which can receive data arbitrarily. So we'd like the observer functions to subscribe to an individual queue. We thought we could do:
public delegate void NewDataAddedDelegate();
public event NewDataAddedDelegate [] NewDataAdded; // can't do this
and in the constructor of qManager:
NewDataAdded = new NewDataAddedDelegate[numberOfQueues];
and in the observer:
qManager.NewDataAdded[0] += new qManager.NewDataAddedDelegate(getNewDataFunc0);
qManager.NewDataAdded[1] += new qManager.NewDataAddedDelegate(getNewDataFunc1);
but no go, since the event is expected to be a delegate type, not an array of delegates type.
Any ideas on how to approach this problem?
No, events don't work like that. Options:
Create another type which exposes the event, and have an array or collection of that type:
// Preferably *don't* just expose an array...
public TypeWithEvent[] Queues { get { ... } }
// Subscription:
qManager.Queues[i].NewDataAdded += ...
Alternatively, don't use events, and just have a method:
private NewDataAddededDelegate[] newDataAdded;
public void SubscribeNewDataAddedHandler(int queue,
NewDataAddedDelegate handler)
{
newDataAdded[queue] += handler;
}
// Subscription
qManager.SubscribeNewDataAddedHandler(0, ...);
Personally it sounds to me like each queue should really be its own object though... make the queue manager exposes a collection of queues, each of which can be subscribed to individually. (i.e. take the first approach.) Otherwise your queue manager is really doing too much work.
There are two approaches you might take there; the first is to have:
private NewDataAddedDelegate[] queues; // init not shown
public void Subscribe(int index, NewDataAddedDelegate handler) {
queues[index] += handler;
}
and use
obj.Subscribe(index, ...);
but you may want to think about synchronization etc around the subscription. A second approach is to create a wrapper class that has the event - then you can use the compiler's synchronization, which is good in C# 4.0:
public class SomeQueue {
public event NewDataAddedDelegate NewDataAdded;
}
and then expose those perhaps via an indexer, so you have
obj.Queues[index].NewDataAdded += ...
Personally, I expect the first is easier. It is only the synchronization that might be a nuisance. I do this in some pub-sub code, and IIRC I just lock during the subscribe.
You need to rethink this by actually applying the observer pattern rather that working on the basis of a fuzzy idea of a pattern.
Define your IObserver and ISubject interfaces and try to understand what's the observer and what are the subjects. In your case sounds like the queues are the subjects, not sure what the observers would be in your domain model.
Once you do this, things will be easier to figure out, and it's simply a matter of implementing the methods declared by your interfaces, for example your subjects (queues) will just call notify (and raise an event if you wanna use delegates) when something happens (item added to the queue).
Hope this helps.
Here is the working code in C#.
QueueManger exposes event NewDataAddedEvent which can be subscribed by one or more observers. Queue calls NewDataAdded() method on QueueManager on data change. QueueManager notifies if there are any subscribers with the parameter Queue. I hope this addresses your question.
using System;
using System.Collections.Generic;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
QueueManager queueManager = new QueueManager();
Observer observer = new Observer(queueManager);
Queue queue1 = queueManager.AddQueue();
Queue queue2 = queueManager.AddQueue();
queue1.OnNewDataAdd();
queue2.OnNewDataAdd();
Console.ReadLine();
}
delegate void NewDataAddedDelegate(Queue queue);
class Queue
{
QueueManager queueManager;
public string id;
public Queue(string id, QueueManager queueManager)
{
this.id = id;
this.queueManager = queueManager;
}
public void OnNewDataAdd()
{
this.queueManager.NewDataAdded(this);
}
}
class QueueManager
{
List<Queue> queues = new List<Queue>();
public Queue AddQueue()
{
Queue queue = new Queue((queues.Count + 1).ToString(), this);
this.queues.Add(queue);
return queue;
}
public event NewDataAddedDelegate NewDataAddedEvent;
public void NewDataAdded(Queue queue)
{
if (NewDataAddedEvent != null)
NewDataAddedEvent(queue);
}
}
class Observer
{
public Observer(QueueManager queueManager)
{
queueManager.NewDataAddedEvent += new NewDataAddedDelegate(queue_NewDataAdded);
}
void queue_NewDataAdded(Queue queue)
{
Console.WriteLine("Notification to the observer from queue {0}", queue.id);
}
}
}
}
Perhaps you could use the Event Aggregator pattern.
Not that you would have to code less, but it could create more clean/maintainable code.