dslreports logo
 
    All Forums Hot Topics Gallery
spc
Search similar:


uniqs
654

PToN
Premium Member
join:2001-10-04
Houston, TX

PToN

Premium Member

C# Timers

Hello,

So on my previous post i showed an app that i am working, the one with the misspell in the UI... ;)

The idea if to turn on the relay for x amount of time, once the time is expired, turn it off and repeat n times.

I am having issues with the Timer raising the Elapsed event before the time is expired. All i want to do is a simple for loop tha

this.processTimer = new Timer();
        this.processTimer.Interval = interval;
        this.processTimer.Elapsed += new ElapsedEventHandler(this.processTimer_Elapsed);
        this.processTimer.Enabled = true;
 
for (int i = 1; i <= eventRepeat; i++)
                {
                    this.executeEventRun(this.devBits);
                }
 

The above turns on the specified relays and turns it off after "interval" is met. The evenhandler only has code to turn off the relays.

The turn on and off only occurs once, if i add a message box in the for loop, before calling executeEventRun(), i can see the relay turning ON and turning off, the new iteration will not start till i click ok.

So i know that my code to turn on and off works, and that my problem is with the Timer...

Any ideas or thoughts?

Thanks.

fnord76
Elder God
Premium Member
join:2002-05-14
Troy, IL

fnord76

Premium Member

I assume you are getting the eventRepeat variable info from somewhere?

PToN
Premium Member
join:2001-10-04
Houston, TX

PToN

Premium Member

Yes: eventRepeat = int.Parse(eRepeatNumberLbl.Text);

cdru
Go Colts
MVM
join:2003-05-14
Fort Wayne, IN

cdru to PToN

MVM

to PToN
Can you post the complete code?
cdru

cdru to PToN

MVM

to PToN
Add "Application.DoEvents();" after line 8.

Or spin off the timer into it's own thread.

PToN
Premium Member
join:2001-10-04
Houston, TX

PToN

Premium Member

Here is what starts everything:
private void startEventClick(object sender, RoutedEventArgs e)
        {
            // Disable some of the UI
            startEventsBtn.IsEnabled = false;
            haltEventBtn.IsEnabled = true;
            eRepeatTb.IsEnabled = false;
            eDurationTb.IsEnabled = false;
            
            eventRepeat = int.Parse(eRepeatTb.Text);
            eventDuration = int.Parse(eDurationTb.Text);
 
            totalTime = eventDuration * eventRepeat;
 
            // Bits to write to device
            devBits = getBitSettings();
 
            if (devBits == 0)
                MessageBox.Show("No Relays have been set. Check Settings", "SigmaDAC Lite Warning",
                    MessageBoxButton.OK, MessageBoxImage.Warning);
            else
            {
                // Timer for count down clock 
                eventTimer = TimeSpan.FromMilliseconds(totalTime);
 
                // Timer for event repeat
                runTimer.Elapsed +=new ElapsedEventHandler(runTimer_Elapsed);
                runTimer.Interval = eventDuration;
                runTimer.AutoReset = true;
 
                remainingTimeLbl.Content = eventTimer.ToString();
                eventNumberLbl.Content = eventRepeat.ToString();
 
                for (int i = 1; i <= eventRepeat; i++)
                {
                    executeEventRun(devBits);
                }
            }
        }
 

Then the executeEventRun():
private void executeEventRun(int bits)
        {
            int writeDev = DeviceHandler.writeReedOutputs(bits);
            runTimer.Start();
 
            if (writeDev < 0)
            {
                MessageBox.Show("Error writing to device: Code: " + writeDev.ToString(), "SigmaDAC Lite Error",
                    MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
 

Finally the method to call once the interval has elapsed:
        void runTimer_Elapsed(object sender, EventArgs e)
        {
            int turnOff = DeviceHandler.writeReedOutputs(0);
 
            if (turnOff < 0)
            {
                MessageBox.Show("Error writing to device: Code: " + turnOff.ToString(), "SigmaDAC Lite Error",
                    MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
 

What i am thinking is that the "for loop" is finishing before the 1st event run is done...

Any ideas..? Ideally the for loop would wait for the runTimer.Interval before continuing...

Thanks.

cdru
Go Colts
MVM
join:2003-05-14
Fort Wayne, IN

cdru

MVM

said by PToN:

What i am thinking is that the "for loop" is finishing before the 1st event run is done...

Any ideas..?

Did you see my last post? Add a "Application.DoEvents();" after you call executeEventRun.

As it is now, the ElapsedEvent will fire, but won't be handled until the current executing code completes. Since you are looping and calling executeEventRun, this ends up running through your loop before the interval fires, only firing once right at the end.

Ideally the for loop would wait for the runTimer.Interval before continuing...

There are multiple ways to handle it. Events, WaitHandle, Semaphores, etc...

PToN
Premium Member
join:2001-10-04
Houston, TX

PToN

Premium Member

Well, i am using WPF so no Windows.Forms for me.

I will investigate threads, waithandle, etc.

Thanks.

cdru
Go Colts
MVM
join:2003-05-14
Fort Wayne, IN

cdru

MVM

WPF DoEvents, or using a dispatcher

Regardless, hopefully you at least know why it's happening now and can work on a solution.

PToN
Premium Member
join:2001-10-04
Houston, TX

PToN

Premium Member

In case anyone is interested.

I ended up using DispatcherTimer. My problem was not only that the for loop was finishing before the Timer events would be Elapsed, but that i was also trying to update UI components that belonged to a different Thread, therefore, the app would just crashed.

DispatcherTimer properly solved my issues.

Thanks.