Chereches Dan Grigore
Chereches Dan Grigore

Reputation: 13

While sequence inside a timer tick in C#

I have a timer of 1 second in C#, with a while sequence in it. My question is if the while sequence is not finished before 1 second, will the timer tick, and restart the while from the beginning?

The part of the code is below, and what it does is that it cycles through the selected objects and changes something. So, if there are a lot of objects selected and I need more than 1 second to change them, will they all be changed?

P.S. I actually want the loop to be broken; a large number of objects will be selected only by mistake, but I just want to be sure that I avoid this possibility. :)

private void timer1_Tick(object sender, EventArgs e)
        {
            TSM.ModelObjectEnumerator myEnum = null;
            myEnum = new TSM.UI.ModelObjectSelector().GetSelectedObjects();

            while (myEnum.MoveNext())
            {
                if (myEnum.Current != null)
                {....}
            }
         } 

Upvotes: 1

Views: 2026

Answers (7)

Esad Međedović
Esad Međedović

Reputation: 1

Get each char from string from txtString and write on label one by one char with timerControl

int g = 0;
private void timerString_Tick(object sender, EventArgs e)
{
    string a = txtString.Text;
    int em = txtString.TextLength;
    if (g < em)
    {
        lblString.Text = lblString.Text + a[g];
        g++;
    }
    else timerString.Stop();
}

Call from

private void btnStringStart_Click(object sender, EventArgs e)
{
    timerString.Start();
    lblString.Text = "";
}

Upvotes: 0

Ovidiu
Ovidiu

Reputation: 1407

From the name of the handler I assume you are using System.Windows.Forms.Timer which is single-threaded. That means the Tick event will fire after the previous one has ended. To break the loop, you will have to execute the code in another thread an use an exit condition.

This is how I usually do it:

private bool running;
private bool restart;

private void DoWork(object item)
{
    running = true;    
    TSM.ModelObjectEnumerator myEnum = null;
    myEnum = new TSM.UI.ModelObjectSelector().GetSelectedObjects();

    while (myEnum.MoveNext() && !restart)
    {       
        //do your stuff
        if (myEnum.Current != null) {....}
    }

    if(restart)
    {
        restart = false;
        ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork));
    }
}

private void timer1_Tick(object sender, EventArgs e)
{
    if (running)
        restart = true;
    else            
        ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork));            
}

Upvotes: 1

usr
usr

Reputation: 171246

Yes, timer ticks can happen concurrently. This means that your timer must be thread-safe.

Except for the UI timer classes (WinForms/WPF). Their tick functions run on the UI thread. With DoEvents you can cause reentrancy even there which is another reason to avoid DoEvents.

Upvotes: 5

Bassam Alugili
Bassam Alugili

Reputation: 17043

I will make it very easy for you;use Thread.Sleep() in another background thread and it is done!

If you know when are you finish than just use AutoResetEvent to keep threads in sync. If you do not have any control on the update no callback , time is unknown I suggest to increase your timer interval!

var thread = new Thread((ThreadStart)delegate
        {
         While(true)
           {
             TSM.ModelObjectEnumerator myEnum = null;
             myEnum = new TSM.UI.ModelObjectSelector().GetSelectedObjects();
             while (myEnum.MoveNext())
              {
                  if (myEnum.Current != null)
                 {....}
              }

              Thread.Sleep(1000);
           }
         }
    thread.Start();

Upvotes: 0

MattR
MattR

Reputation: 641

You could always try something similar to this instead, that way you void having multiple timers tick over and kick off processes. Written in Notepad so please excuse any massive spelling mistakes

private Timer _systemTimer = null;

public MyApp()
{
_systemTimer = new Timer("how ever you set your 1 second);
// Create your event handler for when it ticks over
_systemTimer.Elapsed += new ElapsedEventHandler(systemTimerElapsed);
}

protected void systemTimerElapsed(object sender, ElapsedEventArgs e)
{
_systemTimer.Stop();
//Do what you need to do
_systemTimer.Start();
//This way if it takes longer than a second it won't matter, another time won't kick off until the previous job is done 
}

Upvotes: 0

Boluc Papuccuoglu
Boluc Papuccuoglu

Reputation: 2356

The while loop will not be broken because the timer has ticked again. But in any case, your best bet would be to disable the timer at the beginning of the event handler, and re-enable it again at the end.

Upvotes: 0

AlexF
AlexF

Reputation: 124

A workaround would be to disable the timer at the top of the while event, and re-enable it as you exit the while event.

Upvotes: 0

Related Questions