473,706 Members | 2,414 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

System.Timers.T imer, thread synchronization issues

I have a class that instantiates two Timer objects that fire at
different intervals. My class can be instantiated within a Windows
Form or from a Windows Service. Actions performed by one of the event
handlers may take longer than the interval for either of the timers,
so it's possible for multiple events to fire "simultaneously " and for
events to queue up. I'm attempting to get the timers to sync on some
reference type object, or use System.Threadin g.Monitor to stop them
from re-entering code that's already being executed.

When a timer event fires I use Monitor.TryEnte r(refobj) to attempt a
lock, and simply return on failure (in other words, don't bother
trying to do anything, we're already doing something). The refobj is
an instance of another one of my classes, but this doesn't appear to
be a suitable sync object.

I've tried making the object static/shared so the same object is
consistent across threads. Using this/me doesn't work. I can't use a
this/me reference to a Windows Form because the code could be
instantiated from a Service.

I am using similar code on methods invoked from the container - if a
timer event is doing some operation within the instance, the container
is informed that the object is busy, rather than making it wait for a
turn. If I can't lockdown the object then timers and user requests
are in contention, and the rest of the code outside of these entry
points is not thread-safe.

What type of object do I use to ensure Monitor.Enter(o bject) and
related methods will be respected by any thread? All of the classic
examples on the Net assume we can use 'this' or 'Me' and that we're
running in a Windows Form. This isn't valid for Windows Services,
especially when events like OnPause and OnContinue may get run from a
different thread than the one that started the process.

Thanks!
Nov 13 '06 #1
5 12236

Tony Gravagno wrote:
I have a class that instantiates two Timer objects that fire at
different intervals. My class can be instantiated within a Windows
Form or from a Windows Service. Actions performed by one of the event
handlers may take longer than the interval for either of the timers,
so it's possible for multiple events to fire "simultaneously " and for
events to queue up. I'm attempting to get the timers to sync on some
reference type object, or use System.Threadin g.Monitor to stop them
from re-entering code that's already being executed.

When a timer event fires I use Monitor.TryEnte r(refobj) to attempt a
lock, and simply return on failure (in other words, don't bother
trying to do anything, we're already doing something). The refobj is
an instance of another one of my classes, but this doesn't appear to
be a suitable sync object.

I've tried making the object static/shared so the same object is
consistent across threads. Using this/me doesn't work. I can't use a
this/me reference to a Windows Form because the code could be
instantiated from a Service.

I am using similar code on methods invoked from the container - if a
timer event is doing some operation within the instance, the container
is informed that the object is busy, rather than making it wait for a
turn. If I can't lockdown the object then timers and user requests
are in contention, and the rest of the code outside of these entry
points is not thread-safe.

What type of object do I use to ensure Monitor.Enter(o bject) and
related methods will be respected by any thread? All of the classic
examples on the Net assume we can use 'this' or 'Me' and that we're
running in a Windows Form. This isn't valid for Windows Services,
especially when events like OnPause and OnContinue may get run from a
different thread than the one that started the process.

Thanks!
First off, this/me has nothing at all to do with windows forms. It is
a reference to the current object instance. So, it is valid inside of
a service class - it's valid inside any class (well any instance
method anyway, it isn't valid inside of shared methods since there is
no instance to refer to). In other words, it is perfectly valid to
pass a me reference inside of a windows service to Monitor.TryEnte r.
You should keep in mind that you want to keep locks as small as
possible since they can impact performance. You only need a lock when
accessing shared resources, such as instance variables inside a class -
and then only if the access is read-write. Generally, you don't want
to make the lock object shared (unless the resource being protected is
shared) - because that will cause you to lock every instance of the
class and that is generally not what you want, since usually the
resource that you are protecting is local to that instance.

As for the question about what is appropriate to pass to the various
Monitor methods - well, any reference type will do. Don't use anything
that is a structure - it must be a reference type.
--
Tom Shelton

Nov 13 '06 #2
Please don't misinterpret this as lack of gratitude for your time, but
none of your response helped considering I spelled out the issues in
the OP. Maybe the following clarifications will help.

"Tom Shelton" wrote:
>First off, this/me has nothing at all to do with windows forms. It is
a reference to the current object instance. So, it is valid inside of
a service class - it's valid inside any class (well any instance
method anyway, it isn't valid inside of shared methods since there is
no instance to refer to).
That's all correct.
>In other words, it is perfectly valid to
pass a me reference inside of a windows service to Monitor.TryEnte r.
It's valid, but it doesn't work, that's why I'm here. Just to
clarify, my class is instantiated from a service or other container,
and my class encapsulates the Timer - the service does not instantiate
the timer, so this/me for the service isn't in the scope of the timer
unless I pass it in (which may be necessary the way this is going).

Almost all examples use a timer within Windows Forms where this/me
refers to a Windows Forms object which can be used as a
SynchronizingOb ject. Here is the text from MSDN and it seems everyone
references this text:
When the Elapsed event is handled by a visual Windows Forms
component, such as a button, accessing the component through the
system-thread pool might result in an exception or just might not
work. Avoid this effect by setting SynchronizingOb ject to a Windows
Forms component, which causes the method that handles the Elapsed
event to be called on the same thread that the component was created
on.

It seems so many people who describe timers fall back on this example
that it's become impossible for me to find an example that doesn't use
a Windows Forms component for synchronization . Well, when we're not
running a GUI we don't have a Windows Forms component to use, unless
we just instantiate one just for the purpose, which seems silly. What
I'm finding is that this/me does no good unless we sync on such a
component. I even created my own implementation of ISynchronizeInv oke
and instantiated an object from there to sync on - all events get
marshalled through my proxy but everything I use in
Monitor.TryEnte r(whatever) still fails.

As another example, here's another hint at the problem from a blog,
one of many where this sort of issue is mentioned:
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
(metronome-quality) than Windows timers. The System.Timers.T imer class
will call the timer event handler on a worker thread obtained from the
common language runtime (CLR) thread pool. When using the
System.Timers.T imer, be sure to set the appropriate Principal to the
thread that will execute the Elapsed event because this worker thread
won't inherit the Principal from the main thread.

I'm trying to do what's stated there, by trying to find some reference
type that can be used as a sync object, the above mentioned
"Principal" . But it seems no matter what I use there are worker
threads being used that are not using true references back to the main
instance. So my Monitor.Enter(w hatever) is failing because "whatever"
is different on some of the threads spawned in the threadpool.

>You should keep in mind that you want to keep locks as small as
possible since they can impact performance. You only need a lock when
accessing shared resources, such as instance variables inside a class -
and then only if the access is read-write.
Full agreement. The application code does a lot of things including
communications, handling of single-threaded events from encapsulated
objects, etc - I need to synchronize timer events or all of this falls
apart with threads resetting status values at the wrong time. This
isn't supposed to be a multi-threaded app, but the behaviour of the
Timer is forcing me to recode it like it is.

>Generally, you don't want
to make the lock object shared (unless the resource being protected is
shared) - because that will cause you to lock every instance of the
class and that is generally not what you want, since usually the
resource that you are protecting is local to that instance.
In this case it Is what I want. I want a timer that will tick off
time. Understanding it may tick while I'm still doing something, I
want to throw away the events that I don't need. If Monitor.TryEnte r
fails then I can throw away the tick. Unfortunately, while you're
saying "that will cause you to lock every instance of the class", I
only have one class instance and some of the events (not all!) are
still getting through the TryEnter.

>As for the question about what is appropriate to pass to the various
Monitor methods - well, any reference type will do.
That simply isn't correct. "Any reference type will do" isn't
working, which is what I stated in the OP. As indicated above, I've
instantiated a number of different kinds of reference types, not
structures, that still don't lock out all events. It seems evident
that System.Windows. Forms.Form objects have something that is needed
here that I haven't figured out yet. I haven't yet tried to create a
dummy class that derives from Forms.Control which has an hWnd property
- maybe that's what this thing needs, that's what the trick was before
..NET. As I said above, I think that's silly.
>Don't use anything
that is a structure - it must be a reference type.
Agreed.

Thanks again for your time.
Nov 13 '06 #3
Actually, a lot of people advise *not* locking on "me"/"this", because it
allows external callers to lock on the object, causing possible deadlock
scenarios that were not anticipated.

*ANY* reference type can be used as a lock object. As long as each thread
has access to the same reference (and you don't keep changing that
reference), then it will lock correctly. Depending on the scenario, you
might want to use a static lock object (i.e. "private readonly object
SyncLock = new object();", or you might want to pass a lock object to your
thread when spawning it.

If you can't (for whatever reason) pass the sync-lock (or an encapsulating
class) around, then another solution is to use a named Mutex or similar.

Marc
Nov 13 '06 #4
oops - missed the key keyword... just imagine the "static" was there all
along...

Marc
Nov 13 '06 #5
Problem solved: The VS2005 debugger has a tendency to skip breakpoints
when events queue up. When one-stepping through code, we can expect
control will jump to the event handler on events, but then we'll
usually see it go back to where we originally were - in a
multi-threaded app we're used to this. What I was seeing was that
control would jump to the event handler and stay there, and then
one-stepping would continue into the Monitor block which I thought was
failing. What's really happening is that even if you're using the F11
one-step, all code between the current line and the event handler will
get executed without the debugger walking through it. More break
points might have shown this earlier.

Is that a bug or a feature? Any setting to ensure that "Step Into"
works through ALL code?

I proved that the sync-lock was working by putting an always
incrementing counter at the beginning of my event handler. Then I put
another counter that incremented once past the Monitor.TryEnte r and
decremented on the Monitor.Exit. I have a test to see if that second
counter is ever greater than one and it was not. The first counter
seemed to increment properly whether I saw the event or not.

Yes, "this/me" will work. Sorry for the confusion. I've posted snips
of my code below for anyone else who needs to implement something like
this.
HTH

Thanks again.
"Marc Gravell" wrote:
>Actually, a lot of people advise *not* locking on "me"/"this", because it
allows external callers to lock on the object, causing possible deadlock
scenarios that were not anticipated.

*ANY* reference type can be used as a lock object. As long as each thread
has access to the same reference (and you don't keep changing that
reference), then it will lock correctly. Depending on the scenario, you
might want to use a static lock object (i.e. "private readonly object
SyncLock = new object();", or you might want to pass a lock object to your
thread when spawning it.

If you can't (for whatever reason) pass the sync-lock (or an encapsulating
class) around, then another solution is to use a named Mutex or similar.

Marc

oops - missed the key keyword... just imagine the "static"
was there all along...

The object assigned to System.Timers.T imer.Synchroniz ingObject must
implement ISynchronizeInv oke, so you can't just sync the timer itself
on anything. Not knowing any class that implements this I created my
own, and while it does marshal requests it wasn't necessary for this.
Here is some skeleton code in C# but the same base should work with
VB.

class MyClass()
{
private SyncronizationO bject SyncObject =
new SyncronizationO bject();
// that's my implementation of ISynchronizatio nObject
private static Object SyncLock = new Object();
private static int concurrent = 0; // testing only
private static int events = 0; // testing only
...
}

void Init()
{
tTimer = new System.Timers.T imer();
tTimer.Synchron izingObject = SyncObject;
// That's only a proxy between the event and the handler,
// it can be removed.
tTimer.Elapsed += new
System.Timers.E lapsedEventHand ler(tTimer_Elap sed);
tTimer.Interval = 5000;
tTimer.AutoRese t = true;
tTimer.Enabled = true;
}

void tTimer_Elapsed(
object sender, System.Timers.E lapsedEventArgs e)
{
events += 1;
if (!Monitor.TryEn ter(SyncLock)) { return; }
try
{
concurrent += 1;
if (concurrent 1)
{
throw new Exception("Conc urrency issue1");
// this event was never thrown,
// proof that locking was working
}
HandleTransacti on();
}
finally
{
concurrent -= 1;
if (concurrent 1)
{
throw new Exception("Conc urrency issue2");
}
Monitor.Exit(Sy ncLock);
}
}

The first time the event fires, TryEnter is true and allows execution
of the following code block. The next few times the event fires, the
TryEnter fails as it should. After a while, as I'm walking through
code in debug in VS2005, it looks like events start coming through the
TryEnter like a freight train. What's happening is that VS2005 just
doesn't show all of the code being handled in method
HandleTransacti on, so it just looks like that code is being handled in
different threads.
Nov 13 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
16903
by: Peter Johnsson | last post by:
How come the eventhandler for the timer's elapsed time event is called over and over again, even though the AutoReset property is set to false, if you assign a new value to the timer objects interval property inside the event handler? Example follows: Constructor: mTimer = new System.Timers.Timer(20000); mTimer.AutoReset = false;
2
13209
by: linesh.gajera | last post by:
Hi Guys, I am creating a Windows service that call a routine at given interval. Once routine is complete, windows service should wait for 5 minutes and then call the routine again. I was using System.Timers.Timer but i had to remove it because of known bug(842739). Now i am using System.Threading.Timer. It executes routine fine but the delay time is sporadic, sometimes it executes routine after 5 minutes, sometimes 10 minuete, 13...
4
2298
by: Robert W. | last post by:
I'm building a WinForms app that is a companion to a Pocket PC app. The WinForms app initiates a separate thread that calls a Notification window. This window resides in the lower right corner of the screen and keeps the user informed about what is happening during data transfer to/from the Pocket PC. Everything has been working fine with the Notification window until now. Here's the problem: I'm using RAPI to copy the required CAB...
9
7874
by: Mark Rae | last post by:
Hi, I've seen several articles about using System Timers in ASP.NET solutions, specifically setting them up in Global.asax' Application_OnStart event. I'm thinking about the scenario where I might need to carry out some back-end processing without pausing the individual users' Session while that process runs. E.g. I might provide the ability for a user to upload a text file of job
5
9879
by: Michael C# | last post by:
Hi all, I set up a System.Timers.Time in my app. The code basically just updates the screen, but since the processing performed is so CPU-intensive, I wanted to make sure it gets updated regularly; like every 1.5 secs. or so. I only ran into one issue - the MyTimer_Elapsed event handler was not updating the screen correctly all the time, often leaving large chunks of the screen un-painted for several seconds. On a whim I decided to...
4
3173
by: Kürþat | last post by:
Hi all, I use System.Windows.Forms.Timer with a Windows service but nothing happens after given interval elapsed. It seems timer event does not occur. How can I use timers with Windows Services? Thanks in advance.
7
6051
by: RobKinney1 | last post by:
Hello, Wow...I have one for you all and hopefully I am not understanding this timer object correctly. I have a timer setup that pulses a connection through a socket every 60 seconds. But it seems recently connections just drop off because the timer stops firing. My question is if there is a timeout in the timer event that just shuts down the call if the timer event is taking too long to complete...?
1
414
by: =?Utf-8?B?QnNtZW5nZW4=?= | last post by:
I create the timer like this: StreamingTimer = new System.Timers.Timer(); StreamingTimer.Elapsed += new System.Timers.ElapsedEventHandler(StreamingProc); StreamingTimer.Interval = 1000; StreamingTimer.Enabled = true; StreamingTimer.Start(); To dispose of the timer, I did this:
8
3370
by: Ollie Riches | last post by:
I'm looking into a production issue related to a windows service and System.Timers.Timer. The background is the windows service uses a System.Timers.Timer to periodically poll a directory location on a network for files and then copies these files to another location (on the network) AND then updates a record in the database. The file copying is performed before the database update because the file system is not transactional. The code...
0
8781
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9286
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
9055
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8997
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7911
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
4453
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3149
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2502
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2095
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.