How to use Timer in multi-threaded application - c#

I have designed a Windows application using C#. The application's form consists of a couple of labels and a button. When the application starts, I instantiate a UdpListener and I start a separate thread with it, so as to achieve responsiveness while the listener waits for incoming packets. When data arrives, the listening thread needs to update the form's controls, and for this I have declared delegate functions and checking for each control if Invoking is required prior to seeing them through these functions.
The application worked fine until now. I now want to implement a timer functionality, such that if a pause of longer than 2 seconds of receiving data has been detected, I would like to turn a label red. I am trying to use the System.Timers.Timer class, and following Microsoft's example (https://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.110).aspx), I have implemented as follows:
private static void SetTimer()
{
// Create a timer with a two second interval.
aTimer = new System.Timers.Timer(2000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
aTimer.AutoReset = true;
aTimer.Enabled = true;
}
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0:HH:mm:ss.fff}",
e.SignalTime);
}
I call SetTimer() from my main form. While the above compiles, when I try to substitute Console.... with my controls, say lblStatus, the compiler is complaining that I am trying to reference non static controls from static context. trying to build similar functions as I did for labels and text boxes and using the Invoke method checks does not work either. If anyone has implemented such functionality I would be extremely interested your opinion on this.
In regards to a possible duplication of an existing question on here, please note that I had assumed that the method and event had to be static (as this code was copied from the example cited above), thus the compiler error; I knew what the error meant, I just was puzzled on how I could refer to the form controls from another thread given the static nature of the event. I was also curious as to how come from that static event, Console is still accessible; I guess it's not considered a control. I hope this makes sense to the forum.

You cannot access member variables without an instance reference from a static function. This is because a static function is not part of an instance and it has no access to this.
You should just declare your SetTimer and OnTimedEvent as normal instance methods and declare the timer the same (non-static). That way all your functions will be part of the instance and will have access to other instance variables (controls).
Based on your question, it doesn't seem that you need any of these to be static.

Related

C# Determine which of several timers has expired

I have an array of objects and each object has its own timer. If, when constructing the arrayed objects I pass my own timer event handler for use in the timers, is there any way to tell which object's timer has expired.
If not, it seems all the objects in my array would need to catch their own timers and I'd need to implement a completely different delegate that took something like InnerObject as a parameter so the inner objects own event handler could call it like this: OuterDelegate(this,eventArgs);
All the various ways along the same line are such a ridiculous amount of trouble I can't help but think there must be a better way. On other systems the timer always takes a token that is included in parameters to the event handler but I can't find anything resembling that in .net (core).
The answer to your question is fairly simple. The event handler of the System.Timers.Timer Elapsed event is published with an argument called sender.
_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
}
The sender is actually an instance of the System.Timers.Timer class that elapsed.
So, with this you can know the timer that elapsed...
Further more, this class can be extended/Inherited, which means that you can create your own custom Timer class with has an extra property called Name, which you can use to compare and know which timer elapsed.
Example:
class CustomTimer : System.Timers.Timer {
public string TimerName { get; set; }
//More properties as you need
}
//common handler for array of timers
private void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
var elapsedTimer = sender as CustomTimer;
if (elapsedTimer.TimerName.Equals(/*which ever*/)) {
//continue with logic
}
// continue with logic
}
Well it turns out that System.Timers is complete junk but not your only choice.
System.Threading.Timer has exactly the features I was looking for. I just didn't realize there were two version until I stumbled on certain complaints that clued me to the fact that they are not the same and I finally looked at the threading version.
Edit:
System.Threading.Timer's callback looks like this
public delegate void TimerCallback(object state);
Where state is an arbitrary object passed to the timer during construction. It can encapsulate anything the event handler needs to properly handle the specific instance of the event. You can even set properties or call methods on the object during event handling thus controlling its state based on the timer.
Edit-2
The only thing in the System.Timers implementation that is vaguely similar is the ability to attach a System.ComponentModel.ComponentCollection and the ability to point to a Component within the collection. These are COM objects belonging to System.​Windows.​Forms.​Control. Even if you extend the class to meet your own needs you drag support for unusable properties around with you.
You can extend the System.Threading.Timer just as easily without dragging unnecessary baggage along.

Method will be called more than twice from one thread. How to wait

A C#-method is calling on the main-thread after event raising. Then an another event is firing this same method during the first event is busy with the same method. So during debugging, I see in the calling stack two line in the same method on the same thread.
How can I hinder that the second event waits until the first event is ready with the same method. I'm trying with lock() but it doesn't block the same thread. AutoResetEvent can wait but will be waiting on the same thread.
Somebody has the tip? Thanks.
Your problem is caused by Application.DoEvents(). This method does have its uses but it is dangerous, you stumbled onto one of the reasons : re-entrant calls to events.
So, try
remove and avoid DoEvents().
or make all your eventhandlers capable of or resistant to re-entrancy. Take a critical look at what scenarios are possible with the close button for instance. A simple trick could be:
private bool busy = false;
private void MyHandler(sender s, EventArgs e)
{
if (busy)
return; // giving up, no queuing
busy = true;
// code
busy = false; // maybe in a finally clause
}
You can mark the method with MethodImplAttribute attribute.
Example:
[MethodImpl(MethodImplOptions.Synchronized)]
void Method()
{
....
}
Documentation (MSDN):
MethodImplOptions.Synchronized
Specifies that the method can be executed by only one thread at a time. Static methods lock on the type, whereas instance methods lock on the instance. Only one thread can execute in any of the instance functions, and only one thread can execute in any of a class's static functions.

Which of these functions is the more effective one?

When using the thread, 'invoke' is being used to avoid 'Cross Thread'(1)
but, sometimes 'timer object' is being used to avoid 'CrossThread' (2)
like this(for example)
public partial class Form1 : Form
{
private bool bCheckState = false;
public Form1()
{
InitializeComponent();
}
//Button Click
private void btnWork_Click(object sender, EventArgs e)
{
Thread m_Thread = new Thread(new ThreadStart(Work));
m_Thread.Start();
}
private void Work()
{
bCheckState = true;
// not use invoke
}
private void timer_Tick(object sender, EventArgs e)
{
if (bCheckState)
{
//tbxDisplay is winform's textBox control - printing data
tbxDisplay.Text = bCheckState.ToString();
bCheckState = false;
}
}
}
which one is more effective? 'between (1) and (2)'
Could it be a problem if we scatter the data processed within 'thread' after checking it in the 'timer event', without using 'invoke' or other methods? (We heard that to avoid 'Cross-Thread' when printing the data processed within 'thread', scattering the data in the 'timer event' with additional 'timer object' has been used quite often as it is neither beneficial nor harmful).
Just use a BackgroundWorker instance and handle the ReportProgress and/or RunWorkerCompleted events, which are already in the right thread.
As Ben Voigt suggested, a BackgroundWorker is probably what you should be using here, unless you have a good reason to want to use something else.
"Effective" is a rather vague means of comparison. Its not entirely clear what you're looking for in the two options you are considering.
BackgroundWorkers are simple and easy to understand, and they avoid the use of timers.
Invoke is more effective than a timer in the sense that there will be less of a delay between bCheckState becoming true and the text being updated. It will also be less CPU-intensive, since you won't have a timer polling at a set interval.
The Timer is more effective in the sense that the thread won't have to stop while invoking to update the text, but it is a bit inefficient because it is going to waste CPU time checking if the boolean has changed, and there could also be a delay of up to the timer interval length before the form changes.
As another alternative, BeginInvoke could be used to update the form without the use of a timer, and without the thread having to wait for the invoke to complete. However, if it raises an exception, your thread might not find out unless you also then call EndInvoke, which will also halt execution of the thread until the invoke is complete.
They all have their advantages and disadvantages, and you can't really call any particular one more "effective" in general.

What's the most efficient way to call a method every 20 seconds

I would like to call a method passing a parameter every 20 seconds,
e.g.
public void ProcessPerson(IPerson person)
I’ve been reading through the different Timer options and was wondering if anybody could recommend the most efficient way to do this?
In addition, is there a way to keep the parameter strongly typed rather than use object and then have to convert to IPerson?
Thank you for your help.
A System.Threading.Timer is what you need:
Provides a mechanism for executing a method at specified intervals.
Use a TimerCallback delegate to specify the method you want the Timer to execute. The timer delegate is specified when the timer is constructed, and cannot be changed. The method does not execute on the thread that created the timer; it executes on a ThreadPool thread supplied by the system.
There's also the System.Windows.Forms.Timer:
Implements a timer that raises an event at user-defined intervals. This timer is optimized for use in Windows Forms applications and must be used in a window.
This Windows timer is designed for a single-threaded environment where UI threads are used to perform processing.
And don't forget System.Timers.Timer:
The Timer component is a server-based timer, which allows you to specify a recurring interval at which the Elapsed event is raised in your application.
The server-based Timer is designed for use with worker threads in a multithreaded environment. Server timers can move among threads to handle the raised Elapsed event, resulting in more accuracy than Windows timers in raising the event on time.
So investigate each and decide which one works best in your case.
I would go for System.Threading.Timer. Keep in mind that Windows is not a real-time OS system so there will be some variance on the timing no matter what mechanism you choose.
You did not say if this function will be performing any kind of UI updates, but just in case you should also know that the callback function will be executed on a different thread so in some cases like performing UI updates you will need to take the appropriate action to marshal the request back to the UI thread.
To marshal the request back to the UI thread you can do the following
For WinForms you can use Control.Invoke
For WPF you can use Dispatcher.Invoke
Or the Async variant BeginInvoke
You can use this, just make sure whatever you are doing is thread safe.
using System.Threading;
public void DoStuff(IPerson person)
{
new Timer(ProcessPerson, person, 0, 20000);
}
public void ProcessPerson(object threadState)
{
IPerson person = threadState as IPerson;
// do your stuff
}

Force event handler to run on object's thread, C# .NET

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.

Categories

Resources