Click here to Skip to main content
15,879,326 members
Please Sign up or sign in to vote.
3.80/5 (5 votes)
See more:
C#
public void PauseCheck(int x)
{
    for (int i = 0; i < (x / 10); i++)
    {
      Thread.Sleep(10);
    }
}

This is the way my Thread pauses in some parts of thread methods
x-is time for a pause .
I`ve created in my thread
MIDL
System.Timers.Timer timer;
timer = new System.Timers.Timer();
  timer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimer);
  timer.Interval = BlockTime;

And when my thread enters pausing method for a pause (x=10000) or 10seconds ,and BlockTime is about 5 seconds
timer will elapse only after my thread wakes from sleep.

My question is next :does Thread.Sleep() pause my timer too? and what is the way to get over this problem?
How can I interrupt PauseCheck method when time is elapsed?

P.S this is a programm about dining philosophers and each pause in the thread is time which the user of this programm set before starting the programm,for example
thinking time 10000ms
eating time 10000ms
and blocktime(( timer elapses)and the ph who attempts to take 2 froks fails.and he starts from the very begining)
i began testing my prog and found this error which influences on results.

I suppose ,i got it ,but can fot exmple 3 System.Timers.Timer work at the same time from main form?

I've got the last question: can I define what timer exactly has elapsed?
Posted
Updated 27-Apr-11 11:07am
v11
Comments
Greg Osborne 27-Apr-11 13:18pm    
My question for this is: "Why are you blocking the main thread from running?" If we can understand why you are blocking, we could possibly provided a better method. If you are waiting for another process shouldn't you spawn another thread and provide notification to the main thread that the process has finished? Blocking the main thread is not a good choice as it seems to the user that your app has locked (which it has).
Tirmit 27-Apr-11 13:31pm    
cause it's the emulating of a dining philosophers algorythm and i have to regulate time of eating,thinking and blocks.

So Tirmit you want a class like this thread with a timer?
C#
public class Philosopher
{
    Thread thread;
    Timer tmr;

    public void start()
    {
        thread = new Thread(doWork);
        thread.Start();
    }

    //This method runs in a new thread
    protected void doWork()
    {
        for (int i = 0; i < 100; i++)
        {
            Console.WriteLine("Doing Work for " + i.ToString() + "th time");
        }
        Console.WriteLine("Thread Finished work");

        //initiates the timer inside the created thread. The timer is running yet another new thread
        tmr = new Timer(onTimer, thread, 0, 5000);
        tmr.Change(0, 5000);

        Console.WriteLine("Thread is going to sleep");
        doSleep(50000);

    }

    protected void onTimer(object obj)
    {
        Thread t = obj as Thread;
        t.Interrupt(); // move this below the loop if you want to wake the thread after this work finished.
        for (int i = 0; i < 100; i++)
        {
            Console.WriteLine("Doing Work on Timer elapsed event for " + i.ToString() + "th time");
        }


    }

    protected void doSleep(int x)
    {
        try
        {
            //thread sleeps
            Thread.Sleep(x);
        }
        catch (ThreadInterruptedException e)
        {
            //Thread wakes up here
            tmr.Dispose();
            Console.WriteLine("Timer Elapsed");
            for (int i = 0; i < 100; i++)
            {
                Console.WriteLine("Doing Work on after wakeup for " + i.ToString() + "th time");

                //have to call do work again? Will be in to a endless loop
                //doWork();
            }

        }
    }
}


and call it like

C#
Philosopher p1 = new Philosopher();
   p1.start();
   Philosopher p2 = new Philosopher();
   p2.start();
   Philosopher p3 = new Philosopher();
   p3.start();
   Philosopher p4 = new Philosopher();
   p4.start();


which creates 4 threads and the timer is called inside the thread.
 
Share this answer
 
Comments
Olivier Levrey 28-Apr-11 4:49am    
It looks like a good solution. Have a 5.
Albin Abel 28-Apr-11 5:32am    
Thanks Olivier Levrey
Thread.Sleep pauses the thread in which it is caused. If you call Thread.Sleep from the same thread that uses the timer (usually the UI thread), then yes, it will prevent the thread from handling the timer events.
 
Share this answer
 
Comments
Tirmit 27-Apr-11 13:17pm    
so if I have 5 threads I have to create 5 threads for timers?
#realJSOP 27-Apr-11 13:39pm    
I can't possibly answer that question because I don't know what your program is supposed to do. Besides, I don't personally believe in the use of Timer objects.
Rick Shaub 27-Apr-11 13:38pm    
No. System.Timer uses a threadpool thread for notifications unless you use a synchronizing object. You're not using a synchronizing object, are you?
Olivier Levrey 28-Apr-11 4:47am    
I voted 3 because this is not completely true: it depends what kind of timer you are using. Only System.Windows.Forms.Timer can't be called if the UI thread is sleeping. Other timers are executing on dedicated threads.
1.Why not Thread.Sleep(x) or Thread.SpinWait(x)?
2. Timer runs on separate thread.
3. Try Thread.Interrupt()[^].
 
Share this answer
 
Comments
Tirmit 27-Apr-11 12:59pm    
You mean that Thread.Sleep(x) doesn't influence on timer cause it has a separate thread?
tnd2000 27-Apr-11 13:07pm    
I didn't vote for your answer because I think the OP did not want to create 2 threads. He just wanted PauseCheck interrupted when timer ticks.
CodeHawkz 28-Apr-11 0:40am    
@tnd2000: Have you heard of Dining Philosopher's problem? It is a problem used in teaching Threading :) It uses multiple threads.
@Tirmit: To simulate the time taken for eating, thinking, etc. you should not use a timer. There is a thread for each philoshopher, right? Define a global constant, and use a Thread.Sleep(Constant); after each action (eat, think, etc.) When an action finishes, use the notify method to wake the threads up :)
C#
bool interrupt;
public void PauseCheck(int x)
{
    for (int i = 0; i < (x / 10); i++)
    {
      If(interrupt) break;
      Thread.Sleep(10);
    }
}
public void OnTimer
{
interrupt = true;
}
 
Share this answer
 
It seems to work for me. Are you sure you're calling Timer.Start() when you should? Here is how I tested it:
DateTime start = DateTime.Now;
TimeSpan timespan = new TimeSpan(0,0,0);
volatile AutoResetEvent evnt = new AutoResetEvent(false);
private void button1_Click(object sender, EventArgs e)
{
    System.Timers.Timer timer;
    timer = new System.Timers.Timer();
    timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
    timer.Interval = 5000;
    timer.Start();
    start = DateTime.Now;
    PauseCheck(10000);
    evnt.WaitOne();
    MessageBox.Show("Time: " + timespan);

}

void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    timespan = DateTime.Now - start;
    evnt.Set();
}

public void PauseCheck(int x)
{
    for (int i = 0; i < (x / 10); i++)
    {
        System.Threading.Thread.Sleep(10);
    }
}


Result: "Time: 00:00:05.0005000"
 
Share this answer
 
v2
Comments
Tirmit 27-Apr-11 13:28pm    
Yes,I am shure) but i start it from a thread which pauses.
Rick Shaub 27-Apr-11 13:36pm    
You may want to edit your question and show more of your code so people can see exactly what you're doing. Also, can you explain what you are trying to do?
Tirmit 27-Apr-11 13:57pm    
i just need one of my threads to wait for some time and if the timer elapses it should wake up
Rick Shaub 27-Apr-11 14:03pm    
Then you may want to use an AutoResetEvent Object. You can also use Mutexes or Semaphores. Look at my code to see how an AutoResetEvent is used.
Tirmit 27-Apr-11 14:19pm    
i also use Monitor in this programm but for other purposes,can i use it too?
Take a look at Thread Synchronization[^] and under "Synchronization Events and Wait Handles".

You can use a ManualResetEvent like this:
ManualResetEvent stopEvent = new ManualResetEvent(false);

while (stopEvent.WaitOne(1000) == false)
{
 // Wait for 1 sec or stop it stopEvent is signaled.
}


// When timer tick, stop while loop.
void OnTimer(object sender, System.Timers.ElapsedEventArgs e)
{
  stopEvent.Set();
}
 
Share this answer
 
v2
I didn't fully understood your question. However the answer is Thread.Sleep is a blocking call. It blocks the thread. If your need is executing the timer independent of the blocked thread then use a thread timer which run in a new thread. For example

C#
private System.Threading.Timer tmr;
private void button1_Click(object sender, EventArgs e)
{
    tmr= new System.Threading.Timer(new TimerCallback(OnTimer),Thread.CurrentThread,0,5000);
    tmr.Change(0, 5000);
    PauseCheck(50000);
 }
protected void OnTimer(object obj)
{
    MessageBox.Show("Timer Event is running without pausing");
    Thread t = (Thread)obj;
    t.Interrupt();
}
public void PauseCheck(int x)
{
    for (int i = 0; i < (x / 10); i++)
    {
        try
        {
            Thread.Sleep(10);
        }
        catch (ThreadInterruptedException e) { break; }
    }
    tmr.Dispose();
    MessageBox.Show("Paused Thread is active now");
}


In the above example the timer event run regardless of the blocked thread. But you can't do anything on the blocked thread. In that case instead of sleep you could consider spin wait. Spin wait not work on milliseconds but on iterations.
 
Share this answer
 
v2
Comments
Tirmit 27-Apr-11 13:37pm    
Can you tell me what number equals 1 second in SpinWait(x)?
Albin Abel 27-Apr-11 13:56pm    
That depends on Processor speed, so can't be calculated exactly for a second. I improved my solution with thread interrupt method. This runs the timer and when timer elapsed the slept thread wake up. You may have a look
Tirmit 27-Apr-11 14:06pm    
can i make a *cheat* to stop timer before the method and to count down 10 ms for each itteration ,so that when it is about 0 ,I will stop the pause?
Albin Abel 27-Apr-11 14:17pm    
the timer can be disposed anywhere. But not getting what you mean by "so that when it is about 0 ,I will stop the pause?"
Tirmit 27-Apr-11 14:53pm    
nevermind it doesn't work) I start 5 threads from my form,each thread is a philosopher ,
the problem is that timer is created inside my thread ,cause there is a method that should be called when time is elapsed...
may be it's better to create a list of 5 threads with timers ,so that when i need it ,I will start a the thread with a time,calling it with the help of delegate,but how to get that it has elapsed and call the method that is in a class of a thread?
It seems to me that you should utilize 2 threads atleast and a single thread for each philosopher...

1 Thread is the Main thread.
1 Thread is the Timer Thread

The main thread should start and kick of the timer thread. It should then start up threads for each actor.In the program just ensure you create a Thread[] PhilsopherThreads and each philosopher you create should be created and put to work in one of those threads.

The timer thread should have a high resolution tick such as 1000 ms or 500 ms, this should possibly use Interlocked.CompareExchange to indicate the tick has come by incrementing a private varaible or setting the private varible to DateTime.Now.

In your main thread you will make a worker thread for each actor in your program. In this case the philosopher. Each philosopher thread will follow its logic observing the private variable to determine if he should stop working or continue to work.

In this scenario a philosopher can work or not work as long as he wants. He can observe the private varible to determine if he needs to work further or not. He can be interrupted by the timers as well as by other philosopher threads.

In your main thread you would set the priority to lowest or below normal and while any PhilsopherThreads are working you can SpinWait(0) or Sleep(-1) in the main thread.

At the end of all philosopher threads which are working you can then exit the main thread or do whatever you want to do.


That is how I see it IMHO.
 
Share this answer
 
Comments
jfriedman 27-Apr-11 17:06pm    
In hind sight you dont actually need a timer if you have the philsopher instances.

You can store a lastWorkTime variable and determine from that weather or not you need to work further.
OK, now that I know you're trying to solve the dining philosophers problem, may I suggest that you create one class called philospher and encapsulate all "philospher"-related logic in it. Each one could use a timer to initiate the state change from thinking to eating. Then you can create five instances of this class and observe their behavior.

You'll probably want to create a set of "fork" objects and link to the appropriate philosopher's right and left side somehow. Use Mutexes to simulate the taking of the forks.
 
Share this answer
 
v2
I will clarify about timers and the Sleep function.

1- System.Threading.Sleep blocks the calling thead
2- A System.Threading.Timer or a System.Timers.Timer executes from a dedicated thread, therefore the callback will be called even if the thread which instanciated the timer is sleeping.
3- A System.Windows.Forms.Timer executes from the main thread, therefore the callback will not be called if the main thread is sleeping.

Do this simple test to convince yourself:

C#
static class Program
{
    [STAThread]
    static void Main()
    {
        //uncomment the function you want to test
        //TestThreading();
        //TestTimers();
        //TestWinForms();
    }
    static void TestThreading()
    {
        //"Timer" will be printed every second
        System.Threading.Timer timer = new System.Threading.Timer(
            e => Console.WriteLine("Timer"),
            null, 0, 1000);
        System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
        timer.Dispose();
    }
    static void TestTimers()
    {
        //"Timer" will be printed every second
        System.Timers.Timer timer = new System.Timers.Timer(1000);
        timer.Elapsed += (sender, e) => Console.WriteLine("Timer");
        timer.Enabled = true;
        System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
        timer.Dispose();
    }
    static void TestWinForms()
    {
        //"Timer" will never be printed
        System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
        timer.Interval = 1000;
        timer.Tick += (sender, e) => Console.WriteLine("Timer");
        timer.Enabled = true;
        System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
        timer.Dispose();
    }
}


For the Windows.Forms.Timer, you can replace the infinite sleep with a Sleep(10) inside a loop if you want, but it will not change anything since you are still inside your function. The callback will be called only if your main thread is not busy. Not busy here means you handled all UI events (button clicks, keyboards, ...) and you are waiting for the next event.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900