Raising events on separate thread - c#

I am developing a component which needs to process the live feed and broadcast the data to the listeners in pretty fast manner ( with about 100 nano second level accuracy, even less than that if I can do that) Currently I am raising an event from my code which subscriber can subscribe to. However because in C# event handlers run on the same thread which raises the event, my thread which raises the event will be blocked until all subscribers finish processing the event. I do not have control on subscribers' code, so they can possibly do any time consuming operations in event handler, which may block the thread which is broadcasting.
What can I do so that I can broadcast the data to other subscribers but can still broadcast the stuff quite fast??

100 ns is a very tough target to hit. I believe it will take a deep understanding of what you're doing and why to hit that kind of performance.
However, asynchronously invoking event subscribers is pretty easy to solve.
It's already answered here by, who else, Jon Skeet.
foreach (MyDelegate action in multicast.GetInvocationList())
{
action.BeginInvoke(...);
}
edit:
I should also mention that you need to be running on a real-time operating system to give tight performance guarantees to your users.

It seems like you are looking for tasks. The following is an extension method i wrote for my job that can asynchronously invokes an event so that every event handler is on their own thread. I can't comment on its speed since that has never been a requirement for me.
UPDATE
Based on the comments i adjusted it so that only one task is created to call all of the subscribers
/// <summary>
/// Extension method to safely encapsulate asynchronous event calls with checks
/// </summary>
/// <param name="evnt">The event to call</param>
/// <param name="sender">The sender of the event</param>
/// <param name="args">The arguments for the event</param>
/// <param name="object">The state information that is passed to the callback method</param>
/// <remarks>
/// This method safely calls the each event handler attached to the event. This method uses <see cref="System.Threading.Tasks"/> to
/// asynchronously call invoke without any exception handling. As such, if any of the event handlers throw exceptions the application will
/// most likely crash when the task is collected. This is an explicit decision since it is really in the hands of the event handler
/// creators to make sure they handle issues that occur do to their code. There isn't really a way for the event raiser to know
/// what is going on.
/// </remarks>
[System.Diagnostics.DebuggerStepThrough]
public static void AsyncSafeInvoke( this EventHandler evnt, object sender, EventArgs args )
{
// Used to make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler handler = evnt;
if (handler != null)
{
// Manually calling all event handlers so that we could capture and aggregate all the
// exceptions that are thrown by any of the event handlers attached to this event.
var invocationList = handler.GetInvocationList();
Task.Factory.StartNew(() =>
{
foreach (EventHandler h in invocationList)
{
// Explicitly not catching any exceptions. While there are several possibilities for handling these
// exceptions, such as a callback, the correct place to handle the exception is in the event handler.
h.Invoke(sender, args);
}
});
}
}

You can use these simple extension methods on your event handlers:
public static void Raise<T>(this EventHandler<T> handler, object sender, T e) where T : EventArgs {
if (handler != null) handler(sender, e);
}
public static void Raise(this EventHandler handler, object sender, EventArgs e) {
if (handler != null) handler(sender, e);
}
public static void RaiseOnDifferentThread<T>(this EventHandler<T> handler, object sender, T e) where T : EventArgs {
if (handler != null) Task.Factory.StartNewOnDifferentThread(() => handler.Raise(sender, e));
}
public static void RaiseOnDifferentThread(this EventHandler handler, object sender, EventArgs e) {
if (handler != null) Task.Factory.StartNewOnDifferentThread(() => handler.Raise(sender, e));
}
public static Task StartNewOnDifferentThread(this TaskFactory taskFactory, Action action) {
return taskFactory.StartNew(action: action, cancellationToken: new CancellationToken());
}
Usage:
public static Test() {
myEventHandler.RaiseOnDifferentThread(null, EventArgs.Empty);
}
The cancellationToken is necessary to guarantee StartNew() actually uses a different thread, as explained here.

I can't speak to if this will reliably meet the 100ns requirement but here's an alternative where you'd provide the end user with a way to provide you a ConcurrentQueue that you would fill and they could listen to on a separate thread.
class Program
{
static void Main(string[] args)
{
var multicaster = new QueueMulticaster<int>();
var listener1 = new Listener(); //Make a couple of listening Q objects.
listener1.Listen();
multicaster.Subscribe(listener1);
var listener2 = new Listener();
listener2.Listen();
multicaster.Subscribe(listener2);
multicaster.Broadcast(6); //Send a 6 to both concurrent Queues.
Console.ReadLine();
}
}
//The listeners would run on their own thread and poll the Q like crazy.
class Listener : IListenToStuff<int>
{
public ConcurrentQueue<int> StuffQueue { get; set; }
public void Listen()
{
StuffQueue = new ConcurrentQueue<int>();
var t = new Thread(ListenAggressively);
t.Start();
}
void ListenAggressively()
{
while (true)
{
int val;
if(StuffQueue.TryDequeue(out val))
Console.WriteLine(val);
}
}
}
//Simple class that allows you to subscribe a Queue to a broadcast event.
public class QueueMulticaster<T>
{
readonly List<IListenToStuff<T>> _subscribers = new List<IListenToStuff<T>>();
public void Subscribe(IListenToStuff<T> subscriber)
{
_subscribers.Add(subscriber);
}
public void Broadcast(T value)
{
foreach (var listenToStuff in _subscribers)
{
listenToStuff.StuffQueue.Enqueue(value);
}
}
}
public interface IListenToStuff<T>
{
ConcurrentQueue<T> StuffQueue { get; set; }
}
Since given the fact that you can't hold up processing on other listeners this means multiple threads. Having dedicated listening threads on the listeners seems like a reasonable approach to try, and the concurrent queue seems like a decent delivery mechanism. In this implementation it's just constantly polling, but you could probably use thread signaling to reduce the cpu load using something like AutoResetEvent.

Signals and shared memory are very fast. You could send a separate signal to tell applications to read a message from a shared-memory location. Of course, the signal is still an event that your application has to consume on a high-priority thread if you want low latency. I would include a time-tag in the data so the receiver can compensate for the inevitable latency.

Related

How to make correct encapsulation with multithreading .NET C#

As you can see, I have two classes. RfidReaderHardware generates event in thread "th", but Form running at another thread. As you can see, in form if use Invoke method of ListViewControl. So, question is how to change RfidReaderHardware to resolve encapsulation problem.
public class RfidReaderHardware : IDisposable
{
public event EventHandler<RfidReaderEventArgs> OnNewPackage;
Thread th;
//This method will be called from thread "th"
private void FireNewPackageEvent(UHFPackage package)
{
... code ...
}
... some code ...
}
and we have example code, where this event is using
public partial class PassageForm : Form
{
RfidReaderHardware RfidReader = new RfidReaderHardware(...);
private void Form1_Load(object sender, EventArgs e)
{
RfidReader.OnNewPackage += NewRfidPackage;
}
//not sure, but i think it's running in thread "th"
private void NewRfidPackage(Object o, RfidReaderEventArgs e)
{
ListViewItem item = new ListViewItem();
//from point of encapsulation view it's wrong as you know
CPackageList.Invoke(new Action(() => {CPackageList.Items.Add(item); }));
}
}
question is how to change RfidReaderHardware to resolve encapsulation problem
In fact there is no encapsulation problem. By definition, the relation between event source and subscriber is one to many, hence the source cannot "encapsulate" a logic for a specific subscriber. It's the subscriber choice how to handle the notification. One can ignore it, or handle it immediately, or like in your case handle it on the UI thread either synchronously (using Control.Invoke) or asynchronously (using Control.BeginInvoke).
Not so sure there's any real need to fix this, having the UI object itself deal with the fact that event is fired on the "wrong" thread is not a flaw. As long as you know it is in fact fired on the wrong thread, a documentation requirement.
.NET however has a general mechanism to solve this, it is used in several places inside the .NET Framework code. Your RfidReaderHardware class constructor can copy the value of SynchronizationContext.Current and store it in a field. With the implicit assumption that the object is created by code that runs on the UI thread. When you are ready to fire the event, and the copied object isn't null, you can then use its Post() or Send() method. Which automagically makes the code resume on the UI thread. Regardless of the specific UI class library that was used, works just as well in a WPF or Universal app for example.
Some sample code, it doesn't take much:
public class RfidReaderHardware {
public event EventHandler Received;
public RfidReaderHardware() {
syncContext = System.Threading.SynchronizationContext.Current;
}
protected void OnReceived(EventArgs e) {
if (syncContext == null) FireReceived(e);
else syncContext.Send((_) => FireReceived(e), null);
}
protected void FireReceived(EventArgs e) {
var handler = Received;
if (handler != null) Received(this, e);
}
private System.Threading.SynchronizationContext syncContext;
}

Can events be used in a multi-threaded application safely

In the following code I have two classes, one that runs in a separate thread and fires events, the other that subscribes to this event and receives data from the event. The event code I have based off of Jon Skeet's article http://csharpindepth.com/Articles/Chapter2/Events.aspx
In this article http://www.codeproject.com/Articles/37474/Threadsafe-Events it says...
For this reason, I recommend the same approach that Jon Skeet ends up recommending at the end of Delegates and Events: "don't do that", i.e., don't use events in a multithreaded fashion. If an event exists on an object, then only one thread should be able to subscribe to or unsubscribe from that event, and it's the same thread that will raise the event.
Now obviously my design breaks that, in that it fires the event on a different thread to that it was subscribed on. How could I modify my design so that it adhears to the principle of not using events in a multi-threaded fashion or is this not possible ?
The other way I thought of doing it was just to pass in my callback method as a delegate into class B and call that instead of calling the event?
I may have completely the wrong end of the stick, so any clarification would be appreciated.
Note: I am aware that .Net 4.0 has apparently solved this issue, however I would still be interested in if there is a way to do it pre .Net 4
public delegate void MyDelegate(int a);
class A
{
void main()
{
B bObject = new B();
bObject.MyEvent += new MyDelegate(NiceMethod);
bObject.Run();
}
void NiceMethod(int a)
{
Console.Writeline({0}, a);
}
}
class B
{
readonly object eventLock = new object();
MyDelegate myDel;
public event MyDelegate MyEvent
{
add
{
lock (eventLock)
{
myDel += value;
}
}
remove
{
lock (eventLock)
{
myDel -= value;
}
}
}
//Assume this runs in a new thread and calls back data using MyEvent
//Have ommited thread code for simplicity
public void Run()
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
MyDelegate handler;
lock (someEventLock)
{
handler = myDel;
}
if (handler != null)
{
handler (i);
}
}
}
}
There isn't anything wrong about raising events or listening to events from different threads. It is the responsibility of the listener to deal with being invoked from another thread. As Marc Gravell notes in his comment, adding and removing of listeners to and from events from different threads is (and always has been) supported by the compiler generated add and remove implementations. The only problem is to raise the event in a thread safe fashion, which can be done by synchronizing the access to event via the same kind of spinlock the generated add and remove are using:
class B
{
public event MyDelegate MyEvent;
protected OnMyEvent(int p_Arg)
{
// Delegates are immutable and add/remove default
// implementations always generate a new instance of the
// delegate. Therefore, tTmp (if not null) can be safely invoked
var tTmp =
System.Threading.Interlocked
.CompareExchange(ref MyEvent, null, null);
if (tTmp != null) {
tTmp(p_Arg);
}
}
//Assume this runs in a new thread and calls back data using MyEvent
//Have ommited thread code for simplicity
public void Run()
{
for (int i = 0; i < 100; i++)
{
OnMyEvent(i);
}
}
}
The only thing that could happen is that the listener is invoked after it has been removed from the event list. IMHO, the listener must be able to deal with this situation as it deals with beeing invoked from separate threads...

Question regarding Events in John Skeet's book C# in Depth

I'm studying C# Events on this link and am a little lost on when the following code is called in the context of Main()
/// <summary>
/// Raises the SomeEvent event
/// </summary>
protected virtual OnSomeEvent(EventArgs e)
{
SomeEventHandler handler;
lock (someEventLock)
{
handler = someEvent;
}
if (handler != null)
{
handler (this, e);
}
}
It's code that is right above the sentence
"You could use a single lock for all your events"
Question:
How or when does "OnSomeEvent" get called? I'm not asking about variable locking (as-is the context of the code sample) rather, I'm asking when does the protected virtual method pasted above get called?
The class calls OnSomeEvent when it wants to fire off the event.

INotifyPropertyChanged with threads

I have a
BindingList<T>
which is bound to a datagridview. One property in my class takes long to calculate, so I threaded the action. After the calculation I raise the OnPropertyChanged() event to notify the grid that the value is ready.
At least, that's the theory. But since the OnPropertyChanged Method is called from a differend thread I get some weired exceptions in the OnRowPrePaint method of the grid.
Can anybody tell me how I fore the OnPropertyChanged event to be excecuted in the main thread? I can not use Form.Invoke, since the class MyClass is not aware that it runs in a Winforms application.
public class MyClass : INotifyPropertyChanged
{
public int FastMember {get;set;}
private int? slowMember;
public SlowMember
{
get
{
if (slowMember.HasValue)
return slowMember.Value;
else
{
Thread t = new Thread(getSlowMember);
t.Start();
return -1;
}
}
}
private void getSlowMember()
{
Thread.Sleep(1000);
slowMember = 5;
OnPropertyChanged("SlowMember");
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChangingEventHandler eh = PropertyChanging;
if (eh != null)
{
eh(this, e);
}
}
}
People sometimes forget that the event handler is a MultiCastDelegate and, as such, has all the information regarding each subscriber that we need to handle this situation gracefully without imposing the Invoke+Synchronization performance penalty unnecessarily. I've been using code like this for ages:
using System.ComponentModel;
// ...
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
foreach (EventHandler h in handler.GetInvocationList())
{
var synch = h.Target as ISynchronizeInvoke;
if (synch != null && synch.InvokeRequired)
synch.Invoke(h, new object[] { this, e });
else
h(this, e);
}
}
}
What it does is simple, but I remember that I almost cracked my brain back then trying to find the best way to do it.
It first "grabs" the event handler on a local property to avoid any race conditions.
If the handler is not null (at lease one subscriber does exist) it prepares the event args, and then iterates through the invocation list of this multicast delegate.
The invocation list has the target property, which is the event's subscriber. If this subscriber implements ISynchronizeInvoke (all UI controls implement it) we then check its InvokeRequired property, and it is true we just Invoke it passing the delegate and parameters. Calling it this way will synchronize the call into the UI thread.
Otherwise we simply call the event handler delegate directly.
By design, a control can only be updated by the thread it was created in. This is why you are getting exceptions.
Consider using a BackgroundWorker and only update the member after the long lasting operation has completed by subscribing an eventhandler to RunWorkerCompleted.
Here's something I wrote a while ago; it should work reasonably well, but note the cost of lots of updates...
using System.ComponentModel;
using System.Threading;
public class ThreadedBindingList<T> : BindingList<T> {
SynchronizationContext ctx = SynchronizationContext.Current;
protected override void OnAddingNew(AddingNewEventArgs e) {
if (ctx == null) { BaseAddingNew(e); }
else { ctx.Send(delegate { BaseAddingNew(e); }, null); }
}
protected override void OnListChanged(ListChangedEventArgs e) {
if (ctx == null) { BaseListChanged(e); }
else { ctx.Send(delegate { BaseListChanged(e); }, null); }
}
void BaseListChanged(ListChangedEventArgs e) { base.OnListChanged(e); }
void BaseAddingNew(AddingNewEventArgs e) { base.OnAddingNew(e); }
}
Consideration 1:
Take a look at UIThreadMarshal class and its usage in this article:
UI Thread Marshaling in the Model Layer
You can change the class from static to instance and inject it into your object. So your object will not know about Form class. It will know only about UIThreadMarshal class.
Consideration 2:
I don't think returning -1 from your property is good idea. It looks like a bad design to me.
Consideration 3:
Maybe your class shouldn't use antoher thread. Maybe it's consumer classes who should decide how to call your property: directly or in a separate thread. In this case maybe you need to provide additional property, such as IsSlowMemberInitialized.

Raise Events in .NET on the main UI thread

I'm developing a class library in .NET that other developers will consume eventually. This library makes use of a few worker threads, and those threads fire status events that will cause some UI controls to be updated in the WinForms / WPF application.
Normally, for every update, you would need to check the .InvokeRequired property on WinForms or equivalent WPF property and invoke this on the main UI thread for updating. This can get old quickly, and something doesn't feel right about making the end developer do this, so...
Is there any way that my library can fire/invoke the events/delegates from the main UI thread?
In particular...
Should I automatically "detect" the "main" thread to use?
If not, should I require the end developer to call some (pseudo) UseThisThreadForEvents() method when the application starts so I can grab the target thread from that call?
Your library could check the Target of each delegate in the event's invocation list, and marshal the call to the target thread if that target is ISynchronizeInvoke:
private void RaiseEventOnUIThread(Delegate theEvent, object[] args)
{
foreach (Delegate d in theEvent.GetInvocationList())
{
ISynchronizeInvoke syncer = d.Target as ISynchronizeInvoke;
if (syncer == null)
{
d.DynamicInvoke(args);
}
else
{
syncer.BeginInvoke(d, args); // cleanup omitted
}
}
}
Another approach, which makes the threading contract more explicit, is to require clients of your library to pass in an ISynchronizeInvoke or SynchronizationContext for the thread on which they want you to raise events. This gives users of your library a bit more visibility and control than the "secretly check the delegate target" approach.
In regard to your second question, I would place the thread marshalling stuff within your OnXxx or whatever API the user code calls that could result in an event being raised.
Here's itwolson's idea expressed as an extension method which is working great for me:
/// <summary>Extension methods for EventHandler-type delegates.</summary>
public static class EventExtensions
{
/// <summary>Raises the event (on the UI thread if available).</summary>
/// <param name="multicastDelegate">The event to raise.</param>
/// <param name="sender">The source of the event.</param>
/// <param name="e">An EventArgs that contains the event data.</param>
/// <returns>The return value of the event invocation or null if none.</returns>
public static object Raise(this MulticastDelegate multicastDelegate, object sender, EventArgs e)
{
object retVal = null;
MulticastDelegate threadSafeMulticastDelegate = multicastDelegate;
if (threadSafeMulticastDelegate != null)
{
foreach (Delegate d in threadSafeMulticastDelegate.GetInvocationList())
{
var synchronizeInvoke = d.Target as ISynchronizeInvoke;
if ((synchronizeInvoke != null) && synchronizeInvoke.InvokeRequired)
{
retVal = synchronizeInvoke.EndInvoke(synchronizeInvoke.BeginInvoke(d, new[] { sender, e }));
}
else
{
retVal = d.DynamicInvoke(new[] { sender, e });
}
}
}
return retVal;
}
}
You then just raise your event like so:
MyEvent.Raise(this, EventArgs.Empty);
You can use the SynchronizationContext class to marshall calls to the UI thread in WinForms or WPF by using SynchronizationContext.Current.
I liked Mike Bouk's answer (+1) so much, I incorporated it into my codebase. I am concerned that his DynamicInvoke call will throw a runtime exception if the Delegate it invokes is not an EventHandler delegate, due to mismatched parameters. And since you're in a background thread, I assume you may want to call the UI method asynchronously and that you are not concerned with whether it ever finishes.
My version below can only be used with EventHandler delegates and will ignore other delegates in its invocation list. Since EventHandler delegates return nothing, we don't need the result. This allows me to call EndInvoke after the asynchronous process completes by passing the EventHandler in the BeginInvoke call. The call will return this EventHandler in IAsyncResult.AsyncState by way of the AsynchronousCallback, at which point EventHandler.EndInvoke is called.
/// <summary>
/// Safely raises any EventHandler event asynchronously.
/// </summary>
/// <param name="sender">The object raising the event (usually this).</param>
/// <param name="e">The EventArgs for this event.</param>
public static void Raise(this MulticastDelegate thisEvent, object sender,
EventArgs e)
{
EventHandler uiMethod;
ISynchronizeInvoke target;
AsyncCallback callback = new AsyncCallback(EndAsynchronousEvent);
foreach (Delegate d in thisEvent.GetInvocationList())
{
uiMethod = d as EventHandler;
if (uiMethod != null)
{
target = d.Target as ISynchronizeInvoke;
if (target != null) target.BeginInvoke(uiMethod, new[] { sender, e });
else uiMethod.BeginInvoke(sender, e, callback, uiMethod);
}
}
}
private static void EndAsynchronousEvent(IAsyncResult result)
{
((EventHandler)result.AsyncState).EndInvoke(result);
}
And the usage:
MyEventHandlerEvent.Raise(this, MyEventArgs);
I found relying on the method being an EventHandler doesn't always work and ISynchronizeInvoke doesn't work for WPF. My attempt therefore looks like this, it may help someone:
public static class Extensions
{
// Extension method which marshals events back onto the main thread
public static void Raise(this MulticastDelegate multicast, object sender, EventArgs args)
{
foreach (Delegate del in multicast.GetInvocationList())
{
// Try for WPF first
DispatcherObject dispatcherTarget = del.Target as DispatcherObject;
if (dispatcherTarget != null && !dispatcherTarget.Dispatcher.CheckAccess())
{
// WPF target which requires marshaling
dispatcherTarget.Dispatcher.BeginInvoke(del, sender, args);
}
else
{
// Maybe its WinForms?
ISynchronizeInvoke syncTarget = del.Target as ISynchronizeInvoke;
if (syncTarget != null && syncTarget.InvokeRequired)
{
// WinForms target which requires marshaling
syncTarget.BeginInvoke(del, new object[] { sender, args });
}
else
{
// Just do it.
del.DynamicInvoke(sender, args);
}
}
}
}
// Extension method which marshals actions back onto the main thread
public static void Raise<T>(this Action<T> action, T args)
{
// Try for WPF first
DispatcherObject dispatcherTarget = action.Target as DispatcherObject;
if (dispatcherTarget != null && !dispatcherTarget.Dispatcher.CheckAccess())
{
// WPF target which requires marshaling
dispatcherTarget.Dispatcher.BeginInvoke(action, args);
}
else
{
// Maybe its WinForms?
ISynchronizeInvoke syncTarget = action.Target as ISynchronizeInvoke;
if (syncTarget != null && syncTarget.InvokeRequired)
{
// WinForms target which requires marshaling
syncTarget.BeginInvoke(action, new object[] { args });
}
else
{
// Just do it.
action.DynamicInvoke(args);
}
}
}
}
You can store the dispatcher for the main thread in your library, use it to check if you are running on the UI thread, and execute on the UI thread through it if necessary.
The WPF threading documentation provides a good introduction and samples on how to do this.
Here is the gist of it:
private Dispatcher _uiDispatcher;
// Call from the main thread
public void UseThisThreadForEvents()
{
_uiDispatcher = Dispatcher.CurrentDispatcher;
}
// Some method of library that may be called on worker thread
public void MyMethod()
{
if (Dispatcher.CurrentDispatcher != _uiDispatcher)
{
_uiDispatcher.Invoke(delegate()
{
// UI thread code
});
}
else
{
// UI thread code
}
}
I know this is an old thread, but seeing as it really helped me get started on building something similar, so I want to share my code. Using the new C#7 features, I was able to create a thread aware Raise function. It uses the EventHandler delegate template, and the C#7 pattern matching, and LINQ to filter and set type.
public static void ThreadAwareRaise<TEventArgs>(this EventHandler<TEventArgs> customEvent,
object sender, TEventArgs e) where TEventArgs : EventArgs
{
foreach (var d in customEvent.GetInvocationList().OfType<EventHandler<TEventArgs>>())
switch (d.Target)
{
case DispatcherObject dispatchTartget:
dispatchTartget.Dispatcher.BeginInvoke(d, sender, e);
break;
case ISynchronizeInvoke syncTarget when syncTarget.InvokeRequired:
syncTarget.BeginInvoke(d, new[] {sender, e});
break;
default:
d.Invoke(sender, e);
break;
}
}
I like these answers and examples but inherently by standard you are writing the library all wrong. It's important not to marshal your events to other threads for the sake of others. Keep your events fired where they are and handled where they belong. When the time comes for that event to change threads it's important to let the end developer do that at that point in time.

Categories

Resources