In .NET, what thread will Events be handled in? - c#

I have attempted to implement a producer/consumer pattern in c#. I have a consumer thread that monitors a shared queue, and a producer thread that places items onto the shared queue. The producer thread is subscribed to receive data...that is, it has an event handler, and just sits around and waits for an OnData event to fire (the data is being sent from a 3rd party api). When it gets the data, it sticks it on the queue so the consumer can handle it.
When the OnData event does fire in the producer, I had expected it to be handled by my producer thread. But that doesn't seem to be what is happening. The OnData event seems as if it's being handled on a new thread instead! Is this how .net always works...events are handled on their own thread? Can I control what thread will handle events when they're raised? What if hundreds of events are raised near-simultaneously...would each have its own thread?

After re-reading the question, I think I understand the problem now. You've basically got something like this:
class Producer
{
public Producer(ExternalSource src)
{
src.OnData += externalSource_OnData;
}
private void externalSource_OnData(object sender, ExternalSourceDataEventArgs e)
{
// put e.Data onto the queue
}
}
And then you've got a consumer thread that pulls stuff off that queue. The problem is that the OnData event is fired by your ExternalSource object - on whatever thread it happens to be running on.
C# events are basically just an easy-to-use collection of delegates and "firing" an event just causes the runtime to loop through all of the delegates and fire them one at a time.
So your OnData event handler is getting called on whatever thread the ExternalSource is running on.

Unless you do the marshaling yourself, an event will execute on whatever thread is invoking it; there's nothing special about the way events are invoked, and your producer thread doesn't have an event handler, your producer thread simply said "hey, when you fire this event, call this function". There's nothing in there that causes the event execution to occur on the attaching thread, nor on its own thread (unless you were to use BeginInvoke rather than invoking the event's delegate normally, but this will just execute it on the ThreadPool).

Raising an event with Invoke is the same as calling a method - it gets executed in the same thread you raised it.
Raising an event with BeginInvoke uses ThreadPool. Here are some minor details

you have to use autoresetevent handlers for this problem.....in autoresetevent when producer produses it set the signal then consumer reset its signal and consume.. after consuming consume set signal then only producer produced...
AutoResetEvent pro = new AutoResetEvent(false);
AutoResetEvent con = new AutoResetEvent(true);
public void produser()
{
while(true)
{
con.WaitOne();
pro.Set();
}
}
public void consumer()
{
while (true)
{
pro.WaitOne();
.................****
con.Set();
}
}
private void button1_Click(object sender, EventArgs e)
{
Thread th1 = new Thread(produser);
th1.Start();
Thread th2 = new Thread(consumer);
th2.Start();
}

Related

C# Firing events within the thread they are added

Consider two classes; Producer and Consumer (the same as classical pattern, each with their own threads). Is it possible for Producer to have an Event which Consumer can register to and when the producer triggers the event, the consumer's event handler is run in its own thread? Here are my assumptions:
Consumer does not know if the Producer's event is triggered
within his own thread or another.
Neither Producer nor Consumer are descendants of Control so they don't have
BeginInvoke method inherited.
PS. I'm not trying to implement Producer - Consumer pattern. These are two simple classes which I'm trying to refactor the producer so it incorporates threads.
[UPDATE]
To further expand my problem, I'm trying to wrap a hardware driver to be worked with in the simplest way possible. For instance my wrapper will have a StateChanged event which the main application will register to so it will be notified when hardware is disconnected. As the actual driver has no means other than polling to check its presence , I will need to start a thread to check it periodically. Once it is not available anymore I will trigger the event which needs to be executed in the same thread as it was added. I know this is a classical Producer-Consumer pattern but since I'm trying to simplify using my driver-wrapper, I don't want the user code to implement consumer.
[UPDATE]
Due to some comments suggesting that there's no solution to this problem, I would like to add few lines which might change their minds. Considering the BeginInvoke can do what I want, so it shouldn't be impossible (at least in theory). Implementing my own BeginInvoke and calling it within the Producer is one way to look at it. It's just that I don't know how BeginInvoke does it!
You want to do inter thread communication. Yes it is possible.
Use System.Windows.Threading.Dispatcher
http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.aspx
The Dispatcher maintains a prioritized queue of work items for a specific thread.
When a Dispatcher is created on a thread, it becomes the only Dispatcher that can be associated with the thread, even if the Dispatcher is shut down.
If you attempt to get the CurrentDispatcher for the current thread and a Dispatcher is not associated with the thread, a Dispatcher will be created. A Dispatcher is also created when you create a DispatcherObject. If you create a Dispatcher on a background thread, be sure to shut down the dispatcher before exiting the thread.
Yes there is a way to do this. It relies on using the SynchronizationContext class (docs). The sync context abstracts the operations of sending messages from one thread to another via the methods Send (synchronous for the calling thread) and Post(async for the calling thread).
Let's take a slightly simpler situation where you only want the capture one sync context, the context of the "creator" thread. You would do something like this:
using System.Threading;
class HardwareEvents
{
private SynchronizationContext context;
private Timer timer;
public HardwareEvents()
{
context = SynchronizationContext.Current ?? new SynchronizationContext();
timer = new Timer(TimerMethod, null, 0, 1000); // start immediately, 1 sec interval.
}
private void TimerMethod(object state)
{
bool hardwareStateChanged = GetHardwareState();
if (hardwareStateChanged)
context.Post(s => StateChanged(this, EventArgs.Empty), null);
}
public event EventHandler StateChanged;
private bool GetHardwareState()
{
// do something to get the state here.
return true;
}
}
Now, the creating thread's sync context will be used when events are invoked. If the creating thread was a UI thread it will have a sync context supplied by the framework. If there is no sync context, then the default implementation is used, which invokes on the thread pool. SynchronizationContext is a class that you can subclass if you want to provide a custom way to send a message from the producer to the consumer thread. Just override Post and Send to send said message.
If you wanted every event subscriber to get called back on their own thread, you would have to capture the sync context in the add method. You then hold on to pairs of sync contexts and delegates. Then when raising the event, you would loop through the sync context / delegate pairs and Post each one in turn.
There are several other ways you could improve this. For example, you may want to suspend polling the hardware if there no subscribers to the event. Or you might want to back off your polling frequency if the hardware does not respond.
First, please note that in .NET / the Base Class Library, it is usually the event subscriber's obligation to ensure that its callback code is executing on the correct thread. That makes it easy for the event producer: it may just trigger its event without having to care about any thread affinities of its various subscribers.
Here's a complete example step-by-step of a possible implementation.
Let's start with something simple: The Producer class and its event, Event. My example won't include how and when this event gets triggered:
class Producer
{
public event EventHandler Event; // raised e.g. with `Event(this, EventArgs.Empty);`
}
Next, we want to be able to subscribe our Consumer instances to this event and be called back on a specific thread (I'll call this kind of thread a "worker thread"):
class Consumer
{
public void SubscribeToEventOf(Producer producer, WorkerThread targetWorkerThread) {…}
}
How do we implement this?
First, we need the means to "send" code to a specific worker thread. Since there is no way to force a thread to execute a particular method whenever you want it to, you must arrange for a worker thread to explicitly wait for work items. One way to do this is via a work item queue. Here's a possible implementation for WorkerThread:
sealed class WorkerThread
{
public WorkerThread()
{
this.workItems = new Queue<Action>();
this.workItemAvailable = new AutoResetEvent(initialState: false);
new Thread(ProcessWorkItems) { IsBackground = true }.Start();
}
readonly Queue<Action> workItems;
readonly AutoResetEvent workItemAvailable;
public void QueueWorkItem(Action workItem)
{
lock (workItems) // this is not extensively tested btw.
{
workItems.Enqueue(workItem);
}
workItemAvailable.Set();
}
void ProcessWorkItems()
{
for (;;)
{
workItemAvailable.WaitOne();
Action workItem;
lock (workItems) // dito, not extensively tested.
{
workItem = workItems.Dequeue();
if (workItems.Count > 0) workItemAvailable.Set();
}
workItem.Invoke();
}
}
}
This class basically starts a thread, and puts it in an infinite loop that falls asleep (WaitOne) until an item arrives in its queue (workItems). Once that happens, the item — an Action — is dequeued and invoked. Then the thread goes to sleep again (WaitOne)) until another item is available in the queue.
Actions are put in the queue via the QueueWorkItem method. So essentially we can now send code to be executed to a specific WorkerThread instance by calling that method. We're now ready to implement Customer.SubscribeToEventOf:
class Consumer
{
public void SubscribeToEventOf(Producer producer, WorkerThread targetWorkerThread)
{
producer.Event += delegate(object sender, EventArgs e)
{
targetWorkerThread.QueueWorkItem(() => OnEvent(sender, e));
};
}
protected virtual void OnEvent(object sender, EventArgs e)
{
// this code is executed on the worker thread(s) passed to `Subscribe…`.
}
}
Voilà!
P.S. (not discussed in detail): As an add-on, you could package the method of sending code to WorkerThread using a standard .NET mechanism called a SynchronizationContext:
sealed class WorkerThreadSynchronizationContext : SynchronizationContext
{
public WorkerThreadSynchronizationContext(WorkerThread workerThread)
{
this.workerThread = workerThread;
}
private readonly WorkerThread workerThread;
public override void Post(SendOrPostCallback d, object state)
{
workerThread.QueueWorkItem(() => d(state));
}
// other overrides for `Send` etc. omitted
}
And at the beginning of WorkerThread.ProcessWorkItems, you'd set the synchronization context for that particular thread as follows:
SynchronizationContext.SetSynchronizationContext(
new WorkerThreadSynchronizationContext(this));
I posted earlier that I've been there, and that there is no nice solution.
However, I just stumbled upon something I have done in another context before: you could instantiate a timer (that is, Windows.Forms.Timer) when you create your wrapper object. This timer will post all Tick events to the ui thread.
Now if you're device polling logic is non-blocking and fast, you could implement it directly inside the timer Tick event, and raise your custom event there.
Otherwise, you could continue to do the polling logic inside a thread, and instead of firing the event inside the thread, you just flip some boolean variable which gets read by the timer every 10 ms, who then fires the event.
Note that this solution still requires that the object is created from the GUI thread, but at least the user of the object will not have to worry about Invoke.
It is possible. One typical approach is to use the BlockingCollection class. This data structure works like a normal queue except that the dequeue operation blocks the calling thread if the queue is empty. The produce will queue items by calling Add and the consumer will dequeue them by calling Take. The consumer typically runs it's own dedicated thread spinning an infinite loop waiting for items to appear in the queue. This is, more or less, how the message loop on the UI thread operates and is the basis for getting the Invoke and BeginInvoke operations to accomplish the marshaling behavior.
public class Consumer
{
private BlockingCollection<Action> queue = new BlockingCollection<Action>();
public Consumer()
{
var thread = new Thread(
() =>
{
while (true)
{
Action method = queue.Take();
method();
}
});
thread.Start();
}
public void BeginInvoke(Action method)
{
queue.Add(item);
}
}

Synchronizing Events

I noticed that sometimes my code becomes out of sync if an event fires too quickly. I was wondering if there was a better approach. Under a normal scenario the DeviceOpenedEvent fires after I tell the thread to WaitOne in the TestDevice method, but I have seen in some cases where the event gets fired before the thread has a chance to wait.
protected AutoResetEvent TestAutoResetEvent = new AutoResetEvent(false);
public EventEnum WaitForEvent = EventEnum.None;
bool TestDevice()
{
OpenDevice();
WaitForEvent = EventEnum.DeviceOpened;
TestAutoResetEvent.WaitOne();
WaitForEvent = EventEnum.NoWait;
//Continue with other tests
}
void DeviceOpenedEvent()
{
if (WaitForEvent == EventEnum.DeviceOpened)
TestAutoResetEvent.Set();
}
Under normal circumstances it looks like this:
Open Device
WaitOne()
DeviceOpenedEvent occurs
Set()
This is what I'm seeing my logs sometimes:
Open Device
DeviceOpenedEvent occurs
WaitOne() Essentially stuck here forever
Since OpenDevice is asynchronous (as you mentioned in a comment), it runs in a different thread than its caller. Sometimes it will finish before the next line in source executes:
OpenDevice(); // Async: may finish before the next line executes!
WaitForEvent = EventEnum.DeviceOpened;
When that happens DeviceOpenedEvent doesn't do what you want it to, because WaitForEvent is still EventEnum.None:
if (WaitForEvent == EventEnum.DeviceOpened)
TestAutoResetEvent.Set();
The solution is to change your code so that you signal completion inside a method that's guaranteed to run in the correct order. Here's a simple implementation that removes the enumeration and uses a single wait handle for each event you need to wait on:
protected AutoResetEvent deviceOpenedEvent = new AutoResetEvent(false);
protected AutoResetEvent deviceLockedEvent = new AutoResetEvent(false);
bool TestDevice() {
OpenDevice();
// Do some unrelated parallel stuff here ... then
deviceOpenedEvent.WaitOne();
LockDevice();
deviceLockedEvent.WaitOne();
}
void DeviceOpenedEvent() {
deviceOpenedEvent.Set();
}
It's even easier if you control OpenDevice: just call deviceOpened.Set() when it's done. You could even change OpenDevice to accept the auto reset event and construct it right inside TestDevice, which would reduce your exposure to multithreading bugs.
This should not be a problem. The documentation for AutoResetEvent states:
If a thread calls WaitOne while the
AutoResetEvent is in the signaled
state, the thread does not block.
The following code does not cause WaitOne to block, for instance:
AutoResetEvent waitHandle = new AutoResetEvent(false);
waitHandle.Set();
waitHandle.WaitOne();
Console.WriteLine("After WaitOne");

How to raise an event in C# - Best Approach

I am writing a Windows Form application. It has a thread to perform some operation and when the operation found something it has to notify the main form to change a control.
Currently the notification uses the C# event hadling described in the following MSDN page:
http://msdn.microsoft.com/en-us/library/wkzf914z(VS.71).aspx
But I am not sure about the delegate. Since in the situation I described above the thread invokes the delegate. Is this a thread safe approach to raise the event?
Is it better to implement Windows Messages (SendMessage) in C# and then implement the message handler in the WindowProc.
Unless you need very fine control over the threading, you can probably use BackgroundWorker instead. It handles all of the cross-thread communication for you. You basically put your background code in its DoWork event handler and then pass data back to the UI thread via its ProgressChanged and RunWorkerCompleted events. The link above has a complete example of how to use it.
But in general, simply adding event handlers and raising events is thread-safe as long as you follow some basic guidelines. However, the event handler will be called on the same thread as the code that raises the event. The event handling code may not be expecting to be called on a background thread so that's where BackgroundWorker comes in handy.
The following is a very basic skeleton of a class that raises an event in a thread-safe way. Whether the code that handles the event is thread-safe is another matter entirely.
class MyClass {
public event EventHandler SomethingHappened;
protected virtual void OnSomethingHappened(EventArgs e) {
EventHandler handler = SomethingHappened;
if (handler != null) {
handler(this, e);
}
}
public void DoSomething() {
OnSomethingHappened(EventArgs.Empty);
}
}
Try to use InvokeRequired / Invoke on UI controls. It's better to avoid raw windows message queuing.
The delegate approach isn't all that bad, but the problem is that the event invokes the event handlers in the other thread. That foxes your UI update, which needs to be done in the main thread. So you can use InvokeRequired appropriately in the event handler.
void OnStatusMessage(string s)
{
// might be coming from a different thread
if (txtStatus.InvokeRequired)
{
this.BeginInvoke(new MethodInvoker(delegate()
{
OnStatusMessage(s);
}));
}
else
{
StatusBox.Text += s + "\r\n";
StatusBox.SelectionStart = txtStatus.TextLength;
StatusBox.ScrollToCaret();
}
}
This may not be required when using BackgroundWorker as Josh mentioned. But it's useful if you're considering ThreadPool and WaitCallBack(*) to manage threads.
An issue with using Windows messages is that you have to know which window to send messages to, and multiple subscribers is more painful. (For events you just have to += another handler)
I amn't able to post a hyperlink for WaitCallBack because I don't have multi-link pedigree yet.

Delegates And Cross Thread Exception

Whenever i am updating UI in windows form using delegate it gives me cross thread exception
why it is happening like this?
is there new thread started for each delegate call ?
void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//this call delegate to display data
clsConnect(statusMsg);
}
protected void displayResponse(string resp)
{
//here cross thread exception occur if directly set to lblMsgResp.Text="Test";
if (lblMsgResp.InvokeRequired)
{
lblMsgResp.Invoke(new MethodInvoker(delegate { lblMsgResp.Text = resp; }));
}
}
The DataReceived event is always raised on a threadpool thread. You cannot update any UI control, you have to use Control.BeginInvoke(). There is no point testing InvokeRequired, it is always true.
A couple of things to keep in mind here:
Don't call Control.BeginInvoke for every single character or byte that you receive. That will bring the UI thread to its knees. Buffer the data you get from the serial port until you've got a complete response. Using SerialPort.ReadLine() usually works well, a lot of devices send strings that are terminated by a line feed (SerialPort.NewLine).
Shutting down your program can be difficult. You have to make sure to keep the form alive until the serial port stops sending. Getting an event after the form is closed will generate an ObjectDisposed exception. Use the FormClosing event to close the serial port and start a one second timer. Only really close the form when the timer expires.
Avoid using Control.Invoke instead of BeginInvoke. It can deadlock your program when you call SerialPort.Close().
Lots of ways to get in trouble. Consider using your own thread instead using DataReceived to avoid them.
Port_DataReceived is obviously an async event handler that is being raised by a thread on port monitoring component.
is there new thread started for each
delegate call ?
No, probably not. Your port monitoring component is running the poll on a background thread and the event is being raised from that thread, every time.
The point is that it is being called on a thread other than the UI, so you will need to use Control.Invoke and the patterns associated with it.
Consider this, (and read the post that may illuminate things for you)
void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//this call delegate to display data
UpdateTheUI(statusMsg);
}
private void UpdateTheUI(string statusMsg)
{
if (lblMsgResp.InvokeRequired)
{
lblMsgResp.BeginInvoke(new MethodInvoker(UpdateTheUI,statusMsg));
}
else
{
clsConnect(statusMsg);
}
}
With all of that said, I would be remiss if I didn't point out that the indirection is troubling.
Cross Thread exception happens when some none UI thread changes UI elements. Since UI elements should be changed only in the UI thread this exception is thrown. To help you understand why this happen you will have to publish you code.
Cross thread exception happens when some none UI thread changes the UI elements. To fix this use the Invoke method on the control itself. As an extra you can check InvokeRequired on the control before calling the Invoke method
See msdn

Block while waiting for event

I have an external COM-object that connects to a server and then fire an event when the server is ready. The connect() call is thus asynchronously.
My code looks (a bit...) like
ManualResetEvent waitConnection;
//This is the event that is triggered when server is ready
public void onConnection_event(bool success)
{
if(success)
waitConnection.Set();
}
private string getItem(string itemName)
{
//MYDBCom is a win32 com if that makes any difference
MYDBCom myDBobject = new MYDBCom();
waitConnection = new ManualResetEvent(false);
myDBobject.connect(); //asynchron call.
//wait until server triggers the onConnection_event
waitConnection.WaitOne();
//server is now ready. Get the data from the server.
return myDBobject.getItem(itemName);
}
The problem is that the event is not triggered - it seems to be blocked while waiting in WaitOne. If I instead of using waitOne use
while(!connected)
{
Sleep(100);
DoEvents();
}
the event is triggered.
Any ideas why WaitOne blocks? Are there any other suggestions how to wait until an event triggers?
//Fredrik
Because the event's message pump is on the same thread as your WaitOne call. The thread is waiting and therefore, is not pumping around your messages.
Update
I should add that using DoEvents() is not usually an advisable solution. There are often better ways of handling the scenario such as having the event fired from a different thread outside of your current thread's message pump so that your current thread doesn't need to be running for the event handler to fire.

Categories

Resources