start a timer from different thread in c# - c#

Hi i have stepped into some problem related to timer.
hope somebody can help..
I have a windows form containing a button
when i click on that button i start a parameterised thread
Thread thread1 = new Thread(new ParameterizedThreadStart( execute2));
thread1.Start(externalFileParams);
the code inside the thread executes very well
at the last line of this thread i start a timer
.
public void execute2(Object ob)
{
if (ob is ExternalFileParams)
{
if (boolean_variable== true)
executeMyMethod();//this also executes very well if condition is true
else
{
timer1.enabled = true;
timer1.start();
}
}
}
}
5 but the tick event of the timer is not fired
I am working on VS2008 3.5 framework. I have dragged the timer from toolbox and set its Interval to 300 also tried to set Enabled true/false
method is timer1_Tick(Object sender , EventArgs e) but its not fired
can anybody suggest what I am doing wrong?

You could try to start the timer this way:
Add in form constructor this:
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 1 second.
aTimer.Interval = 1000;
Add this method to Form1:
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
//do something with the timer
}
On button click event add this:
aTimer.Enabled = true;
This timer is already threaded so no need to start a new thread.

It is true what Matías Fidemraizer says. But, there is a work around...
When you have a control on your form that is invokable (eg. a statusbar), just invoke that one!
C# Code sample:
private void Form1_Load(object sender, EventArgs e)
{
Thread sampleThread = new Thread(delegate()
{
// Invoke your control like this
this.statusStrip1.Invoke(new MethodInvoker(delegate()
{
timer1.Start();
}));
});
sampleThread.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
MessageBox.Show("I just ticked!");
}

System.Windows.Forms.Timer works in a single-threaded application.
Check this link:
http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx
Remarks says:
A Timer is used to raise an event at
user-defined intervals. This Windows
timer is designed for a
single-threaded environment where UI
threads are used to perform
processing. It requires that the user
code have a UI message pump available
and always operate from the same
thread, or marshal the call onto
another thread.
Read more "Remarks" section and you'll find that Microsoft recommends that you use this timer synchronizing it with the UI thread.

I would use a BackgroundWorker (instead of a raw thread). The main thread would subscribe to the worker's RunWorkerCompleted event: The event fires in your main thread when the thread completes. Use this event handler to restart your timer.

Related

C# EvenHandler only updates once

I'm trying to get more familiar with eventhanlders, but my current even only updates once, I want it to update until I close the application.
This is my code:
private static event EventHandler Updater;
Updater += Program_updater;
Updater.Invoke(null, EventArgs.Empty);
Application.Run();
private static void Program_updater(object sender, EventArgs e)
{
KeyUtils.Update();
Framework.Update();
}
But like I said, it will only update once, I want it to update until I close my application. I know I can just do a While(true) but I rather not.
I think you want a Timer here:
Timer aTimer = new System.Timers.Timer(2000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += Program_updater;
// Have the timer fire repeated events (true is the default)
aTimer.AutoReset = true;
// Start the timer
aTimer.Enabled = true;
Specify callback:
private void Program_updater(Object source, System.Timers.ElapsedEventArgs e)
{
KeyUtils.Update();
Framework.Update();
}
Now every 2 seconds (or specify any other interval) callback OnTimedEvent will be called.
It is absolutely normal that your event is fired only once because the application starts only once.
What you acctualy need is to set up a timer and do some work on its tick.
Please have a look on example in answer for that question Simple example of the use of System. Timers. Timer in C#
Well it only updates once since you only invoke it once (I don't really get the context where your code runs since you both declare a static variable and invokes it on the same scope which is impossible).
If you want something to occur periodically you should use Timer, or in some cases AutoResetEvent/ManualResetEvent.
EventHandlers should be used only when you work as event driven which mean you want your handler to invoke When something happens
Here an example for [System.Timers.Timer][2] with your handler:
//Invoke every 5 seconds.
Timer timer = new Timer(5000);
//Add your handler to the timer invocation list.
timer.Elapsed += Program_updater;
//Start the timer.
timer.Start();
Also you need Program_update's signature to look like that:
private void Program_updater(object source, ElapsedEventArgs e)

Windows Forms Timer doesn't stop. How is that possible?

During debugging I can see that after Timer.Stop() or Timer.Enabled = false commands are executed, Timer is still running (Timer.Enabled = true). How is that possible?
This is possible when you stop the timer on a worker thread. For example:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
Timer timer1;
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
timer1 = new Timer();
timer1.Interval = 3000;
timer1.Start();
var t = new System.Threading.Thread(stopTimer);
t.Start();
}
private void stopTimer() {
timer1.Enabled = false;
System.Diagnostics.Debug.WriteLine(timer1.Enabled.ToString());
}
}
Output:
True
The timer must be stopped by the UI thread, the class takes care of it automatically. Quite similar to Control.BeginInvoke(). There's an explicit race, the Tick event handler can run after you stopped it. This can also happen on the UI thread if the very first timer you create is created on a worker thread. A splash screen for example. That's not healthy, you ought to fix that.
Calling Start after you have disabled a Timer by calling Stop will cause the Timer to restart the interrupted interval. If your Timer is set for a 5000-millisecond interval, and you call Stop at around 3000 milliseconds, calling Start will cause the Timer to wait 5000 milliseconds before raising the Tick event.
bear also in mind
Calling Stop on any Timer within a Windows Forms application can cause messages from other Timer components in the application to be processed immediately, because all Timer components operate on the main application thread. If you have two Timer components, one set to 700 milliseconds and one set to 500 milliseconds, and you call Stop on the first Timer, your application may receive an event callback for the second component first. If this proves problematic, consider using the Timer class in the System.Threading namespace instead.
http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.stop.aspx
public void EnableTimer(bool state)
{
if (this.InvokeRequired) {
this.Invoke(new Action<bool>(EnableTimer), state);
} else {
this.Timer1.Enabled = state;
}
}
Try this code...

How to start a BackgroundWorker on a specific time?

I am having a problem in running a backgroundworker on a given specific time.
My code runs the backgoundworker in only one second.
I want to increase the Interval time in my background.
I am using this line of code to run a background in a button click Event:
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
Then in backgroundWorker1_DoWork:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
backgroundWorker1.CancelAsync();
}
At last in backgroundWorker1_RunWorkCompleted:
private void backgroundWorker1_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
I want to run the background continuously but for every 5 seconds or more than 5.
There would be a great appreciation if someone could help me,
Thanks in advance.
Run-time
Timer class represents a Timer control and used to create a Timer at run-time. The following code snippet creates a Timer at run-time, sets its property and event handler.
Timer t = new Timer();
t.Interval = 2000;
timer1.Enabled = true;
timer1.Tick += new System.EventHandler(OnTimerEvent);
The event handler code looks like following.
private void OnTimerEvent(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
Here is demo : C# Timer Tutorial
Check documentation on msdn : http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx
you could add a Timer setting the interval to how often you want the background worker to run and on the timers elapsed event you could start your background worker.
you will want to check that the background worker is not busy before you attempt to start it again though. If this situation occurs then you might consider immediately starting the background worker again when it completes. (if you want it to run at least once every 5 secs)
If you want it to wait 5 seconds after completion, then you need to stop the timer before you start the background worker, then in the background workers completed event you need to reset the timer and start it again.
EDIT
after one of your comments below it seems that you have many backgroundworkers, in which case using one of the other approaches which inserts a delay in the background workers completed event before starting the backgroundworker again is probably a better solution.
You could insert the delay using Thread.Sleep() as has been suggested or you could maybe create a timer in the function and assign a delegate to the timers elapsed event which restarted the background worker. Something along these (untested) lines:
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Timer timer = new Timer();
timer.Interval = 5000;
timer.Enabled = true;
timer.Elapsed+=delegate (object sender, ElapsedEventArgs args)
{
backgroundWorker1.RunWorkerAsync();
};
timer.Start ();
}
Do you need it to run exactly every five seconds or not more often than five seconds? If it's the latter you could call Sleep(5000) on the Thread.CurrentThread just before your BackgroundWorker finishes its DoWork() method.
The easiest solution would be to let the thread sleep for 5 seconds in the beginning of backgroundWorker1_DoWork: Thead.Sleep(5000).
Alternatively, you can set a timer in RunWorkerCompleted that expires in 5 seconds and then starts the BackgroundWorker again.
If you want to use BW try this:
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Thread.Sleep(5000);//wait for 5s then run it again
backgroundWorker1.RunWorkerAsync();
}
Couldn't you use a Timer to start your BackgroundWorker?

Accessing a Progress bar from (System.Timer)Timer Event gives "Cross-Thread Operation Not Valid)

I am designing a form in which I have to increase a Progress bar while an operation is being performed simultaneously (In other words, I am showing the progress of this operation).
This operation takes 50 seconds. So I have used a System.Timer to Increase the Progress bar.
There isn't a single thread in my code. When I write Progress_bar.PerformStep() in Timer Event Handler, it gives error as "Cross Thread Operation Not Valid".
[From this error I analyzed that System.Timer must be creating a Thread and Runs the timer in it to perform multiple tasks.]
What should I do to increase my progress bar after every Second?
I tried solution given in this question. It removed the error but Now I can't see the progress bar increasing. Means it Starts.... No Increase for 50 sec and after it 100%.
Code is as follows:
Timer Declaration (It is Global):
public System.Timers.Timer Thetimer = new System.Timers.Timer(1000);
Event Declaration (This is in Constructor to make it...err...Public [May not be a correct word]):
Thetimer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
Call:
Thetimer.Start();
blRetVal = FunctionToBeExecuted(parameter);
Thetimer.Stop();
Event Handler:
void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
//StatusBar.PerformStep(); -- Tried This. It gives the Error
/* This doesn't give an error but Another issue Arises */
if (InvokeRequired)
{
BeginInvoke(new Action(StatusBar.PerformStep));
}
else
StatusBar.PerformStep();
}
P.S. I am using C# and Visual Studio 2008
When you initialize the Timers.Timer object for use with a Windows Form, you must set the SynchronizingObject property of the timer instance to be the form.
systemTimersTimerInstance.SynchronizingObject = this; // this = form instance.
http://msdn.microsoft.com/en-us/magazine/cc164015.aspx
Rudy =8^D
It sounds like you're performing your "background" operation on the main thread, which is why your progress bar doesn't update when you invoke it.
Have a look at BackgroundWorker.
OK. Jon B is right. You'll have to have the long running task in a thread, there is no way around that. Simplified, you're doing this:
public partial class Form1 : Form
{
// ...
public System.Timers.Timer timer = new System.Timers.Timer(1000);
private void Form1_Load(object sender, EventArgs e)
{
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_elapsed);
timer.Start();
// Simulates your long running task (FunctionToBeExecuted)
// NOTE: This freezes the main UI thread for 10 seconds,
// so nothing will be drawn *at all*
Thread.Sleep(10000);
timer.Stop();
}
void timer_elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (InvokeRequired)
this.BeginInvoke(new Action(progressBar1.PerformStep));
else
progressBar1.PerformStep();
}
}
As you can see in the Load event, you're not only halting the progress bar, you're halting the main UI thread. That's just not acceptable to most users and all good developers should have another option in their toolset.
The only way around this (except running another process) is running the task in a different thread. One of the easiest ways is using a BackgroundWorker, it's really easy. Here are the changes you need:
public partial class Form1 : Form
{
// ...
private void Form1_Load(object sender, EventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Your work is completed, not needed but can be handy
// e.g. to report in some way that the work is done:
progressBar1.Value = progressBar1.Maximum;
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_elapsed);
timer.Start();
// Simulates your long running task (FunctionToBeExecuted)
// Your main UI thread is free!
Thread.Sleep(10000);
timer.Stop();
}
// ...
}

BackgroundWorker thread and Timer logic

I've been trying to get the logic right for my timer and backgroundworker thread. Granted I don't fully understand the whole system despite all my reading. the following are excerpts of code concerned:
My polling button :
private void pollStart_Click(object sender, EventArgs e)
{
tst_bgw = new BackgroundWorker();
//mandatory. Otherwise will throw an exception when calling ReportProgress method
tst_bgw.WorkerReportsProgress = true;
//mandatory. Otherwise we would get an InvalidOperationException when trying to cancel the operation
tst_bgw.WorkerSupportsCancellation = true;
tst_bgw.DoWork += tst_bgw_DoWork;
tst_bgw.ProgressChanged += tst_bgw_ProgressChanged;
tst_bgw.RunWorkerCompleted += tst_bgw_RunWorkerCompleted;
tst_bgw.RunWorkerAsync();
}
which I think is right so far
my Background worker thread:
private void tst_bgw_DoWork(object source, DoWorkEventArgs e)
{
m_timer = new System.Timers.Timer();
m_timer.Interval = 1000;
m_timer.Enabled = true;
m_timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
if (tst_bgw.CancellationPending)
{
e.Cancel = true;
return;
}
}
and the elapsed tier event code:
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
if (powerVal > 3250)
{
m_timer.Stop();
tst_bgw.CancelAsync();
}
else
{
string pow;
int progressVal = 100 - ((3250 - powerVal) / timerVal);
uiDelegateTest tstDel = new uiDelegateTest(recvMessage);// the recvMessage function takes a textbox as an argument and directs output from socket to it.
pow = construct_command("power", powerVal);
sData = Encoding.ASCII.GetBytes(pow);
if (active_connection)
try
{
m_sock.Send(sData);
Array.Clear(sData, 0, sData.Length);
tstDel(ref unit_Output);// Read somewhere that you can only modify UI elements in this method via delegate so I think this is OK.
m_sock.Send(time_out_command);
tstDel(ref unit_Output);
tst_bgw.ReportProgress(progressVal);
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
tst_bgw.ReportProgress(powerVal, progressVal);
powerVal = powerVal + pwrIncVal;
}
I'd just like to know a few other things; am I using the right timer (not that I think it should matter greatly but it was suggested that this might be the best timer for what I want to do) and canI really modify UI elements in the DoWork method only through delegates and if yes are there sepcial considerations to doing so.
Sorry about the long posting and thank you for your time.
There is lots wrong with this code.
1) You aren't disposing of your background worker. BackgroundWorkers must be disposed of after use. They are designed to be used as winforms components and would normally be added to a window via the designer. This will ensure it is created with the form and disposed of when the form is.
2) All you are doing in your dowork method is creating a new timer and running it. There is no point of doing this in a background worker because it will happen so quickly anyway.
3) You will recreate the timer every time you run the background worker again. But you aren't ever stopping or disposing of the old timer, you are just overwriting the member.
I recommend you get rid of the BackgroundWorker completely and just use a timer. Create the timer in the forms constructor and make sure you dispose of it in the forms dispose method. (Or use the designer to add it to the form). In the pollstart_click method just start the timer. (If you have a poll stop method, you can stop the timer in that)
You don't need both a BackgroundWorker and a Timer to accomplish your goal. From what you have posted it looks like you want to have the user click a button which starts a polling process that quits at a certian point.
Your polling model really suggests a timer would work just fine.
If you use a Timer I would Initialize the timer after the InitializeComponent() call with something like
private void InitializeTimer()
{
this.timer = new Timer();
int seconds = 1;
this.timer.Interval = 1000 * seconds; // 1000 * n where n == seconds
this.timer.Tick += new EventHandler(timer_Tick);
// don't start timer until user clicks Start
}
The button_click will simply
private void button_Click(object sender, EventArgs e)
{
this.timer.Start();
}
Then on the timer_Tick you will need to do your polling and you should be able to update your UI from there if the timer is on the UI thread like this
void timer_Tick(object sender, EventArgs e)
{
if( determineIfTimerShouldStop() )
{
this.timer.Stop();
}
else
{
// write a method to just get the power value from your socket
int powerValue = getPowerValue();
// set progressbar, label, etc with value from method above
}
}
However if the timer thread is not on the same thread as the UI you well get an exception while trying to update the UI. In that case you can use the Invoke that DataDink mentions and do something like this
void timer_Tick(object sender, EventArgs e)
{
if( determineIfTimerShouldStop() )
{
this.timer.Stop();
}
else
{
// write a method to just get the power value from your socket
int powerValue = getPowerValue();
// set a label with Invoke
mylabel.Invoke(
new MethodInvoker( delegate { mylabel.Text = "some string"; } )
);
}
}
Given the code you posted you really didn't need to do both a BackgroundWorker and a Timer, but I have had instances where I have used a BackgroundWorker to do work when a timer is called so that I could have a timer update UI periodically and have a manual button to Refresh the UI. But I wasn't updating my UI quite the way you are.
If you still have the need to do both, here is, roughly, how you can flow your app...
Create an
InitailizeBackgroundWorker() method
along with the InitializeTimer so you have
it already initalized before the
Timer fires.
Then set the Timer.Tick
to call the
BackgroundWorker.RunWorkerAsync()
Then you can do all the UI updates from within the RunWorkerAsync by
using the
BackgroundWorker.ReportProgress().

Categories