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?
Related
I have an app which uses DispatcherTimer to manage time, countdown things etc. and I do have multiple counters turned on while app is open. But the time is a little bit delayed, I'd say about 3-5 seconds per minute. This is part of the code I'm using:
DispatcherTimer ob = new DispatcherTimer();
ob.Interval = new TimeSpan(0, 0, 1);
private void bob_Click(object sender, RoutedEventArgs e) //Button starting countdown
{
ob.Start();
tikOb = 140;
ob.Tick += new EventHandler(ob_Tick);
}
void ob_Tick(object sender, EventArgs e)
{
tob.Text = tikOb.ToString();
if (tikOb > 0)
{
tikOb--;
}
else
{
ob.Stop();
tob.Text = "STOPPED";
ob.Tick -= new EventHandler(ob_Tick);
}
//Between these there is a code which is irrelevant in this case.
private void stopob_Click(object sender, RoutedEventArgs e) //Button breaking countdown
{
ob.Tick -= new EventHandler(ob_Tick);
ob.Stop();
tob.Text = "ON";
{
Can anyone tell me why is this happening? Did I do anything wrong inside the code? Oh, I also have another one in the code which uses different variables etc. It's completely separated. Thanks in advance!
The DispatcherTimer is executed on the UI thread. If the UI thread is currently busy doing other work for more than the interval, it will delay the execution of the Timer event and invoke it once it is free of prior work. If you need more precise scheduling, you should go for a time than runs in the background, like System.Threading.Timer or Task.Delay which can be awaited, if you're using .NET 4.5 and above. If you use the Timer and then invoke UI thread logic, you will have to remember to marshal back work to the UI thread.
How do I execute an infinite loop in C# with a 1 minute delay per iteration?
Is there any way to do it without using some kind of variable with x++ and setting x to some incredibly large number?
Solution1 :
If you want to wait for 1 minute without hanging your Main Thread, it is good to use Timer Control.
Step 1: You need to Subscribe to the Timer Tick event.
Step 2: Set the Interval property of the Timer to 60000 milliseconds for raising the event for every Minute.
Step 3: In Tick Event Handler just do ehatever you want to perform.
Step 4: you can Call the timer1.Stop() method whenever you want to stop the timer.
Note : if you don't stop the timer it becomes infinite.
if you want to stop the timer you can call timer1.Stop();
System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
timer1.Interval=60000;//one minute
timer1.Tick += new System.EventHandler(timer1_Tick);
timer1.Start();
private void timer1_Tick(object sender, EventArgs e)
{
//do whatever you want
}
Solution 2:
EDIT : From the below comments : if the OP(Original Poster) is Trying to run this from Console Application System.Timers.Timer can be used
Note : instead of Handling Tick Event , OP has to handle the Elapsed Event.
Complete Code:
class Program
{
static System.Timers.Timer timer1 = new System.Timers.Timer();
static void Main(string[] args)
{
timer1.Interval = 60000;//one minute
timer1.Elapsed += new System.Timers.ElapsedEventHandler(timer1_Tick);
timer1.Start();
Console.WriteLine("Press \'q\' to quit the sample.");
while (Console.Read() != 'q') ;
}
static private void timer1_Tick(object sender, System.Timers.ElapsedEventArgs e)
{
//do whatever you want
Console.WriteLine("I'm Inside Timer Elapsed Event Handler!");
}
}
while (true)
{
System.Threading.Thread.Sleep(60000);
}
Now if we assume you don't want this thread to block and you're ok dealing with threading concerns, you can do something like this:
System.Threading.Tasks.Task.Run(() =>
{
while (true)
{
// do your work here
System.Threading.Thread.Sleep(60000);
}
});
The Task will put your work on a ThreadPool thread, so it runs in the background.
You can also look at a BackgroundWorker if that's more geared toward what you want.
for(;;)
{
//do your work
Thread.Sleep(60000);
}
This is not optimal but does exactly what it's asked.
From a similar question on MSDN:
>
System.Threading.Thread.Sleep(5000);
this codes make your application waiting for 5 seconds.
Change the number as necessary for the amount of time you want to sleep for (for one minute, this would be 60000).
You can put this where you want in your while loop
while(true){
Sleep(60000);}
This would be a blocking call, so you would want to put it on its own thread or any kind of UI that you would have would hang badly.
Sleep is in the System.Threading.Thread namespace.
I have a while loop running in my .NET backgroundworker. I would like to end the loop when Timers.Timer reaches 0.
Problem is that since I'm working in another thread (backgroundworker), my timer has to be instantiated in that same thread. So I can't set any private boolean timer_Elapsed. Nether do I know how to give reference of boolean thro event.
Code Example:
private bool timer_Elapsed = false;
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
System.Timers.Timer timer = new System.Timers.Timer();
Set_Timer(timer);
timer.Start();
while(timer_Elapsed) //Has to be a boolean that indicates if timer elapsed
{
this.Do_Proces();
}
}
private void Set_Timer(System.Timers.Timer timer)
{
timer.Interval = 200;
timer.Elapsed += new ElapsedEventHandler(timer_ElapsedEvent);
}
private void timer_ElapsedEvent(object source, ElapsedEventArgs e)
{
timer_Elapsed = true; //I can't set my private boolean since it got instantiated in another thread
}
Particular questions in code. I'm new with this kind of stuff.
Any suggestions? Thanks in advance
EDIT: To clarify, I want the Do_Proces() to run for 200 milliseconds, when that time passed, I want it to stop. When it stops after 200 millisec, I want to and update GUI with data generated in backgroundWorker. Then check if user wants the proces to stop, if not, I want it to run again.. I use the timer because the thread will have to get restarted to much, this will have effect on the main thread as well, effecting the user experience badly.
Is the timer serving any other purpose other than listed here? If not, you may just want to record the current time at the beginning of your BackgroundWorker method, and change the condition on the while loop to check if the required amount of time has elapsed.
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
TimeSpan timeout = TimeSpan.FromMinutes(5);
DateTime start_time = DateTime.Now;
while(DateTime.Now - start_time < timeout)
{
this.Do_Proces();
}
}
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.
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();
}
// ...
}