C# Executing a method with intervals using system.threading.timer - c#

Hello
Lets say I have a console application, that looks like this
class Program
{
static void Main(string[] args)
{
}
public void DoSomething()
{
Console.WriteLine("Hello World");
}
}
}
I wan't to execute my DoSomething method every 10'th second by using System.Threading.timer. Can anyone give an example of how that is done?
Thanks in advance :)

Timer timer1 = new Timer(10000);
timer1.Enabled = true;
timer1.Elapsed += new ElapsedEventHandler(timer1_Elapsed);
timer1.Start();
static void timer1_Elapsed(object sender, ElapsedEventArgs e)
{
//Do Something
}

The documentation page for the System.Threading.Timer class has a lengthy, good example.

Related

GUI updates only after the worker thread has ended

I have a Windows Form application and managed DLL in one solution. DLL contains some time consuming functions during which I wish to update the Form contents (callback from the DLL to the Form with progess updates). I have the following code:
Form code, where I initialize the DLL and give it a callback function in the Initialize method. I also start a separate Thread to periodicly check the message_queue for new messages from the DLL. The DLL function is also called in a separate Thread (non blocking for the UI).
private LibraryDLL library_dll;
private ConcurrentQueue<string> message_queue;
public MainForm()
{
InitializeComponent();
library_dll = new LibraryDLL();
message_queue = new ConcurrentQueue<string>();
library_dll.Initialize(ProcessMessage);
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
string message;
if (message_queue.TryDequeue(out message))
{
PrintMessage(message);
}
}).Start();
}
private void ProcessMessage(string message)
{
message_queue.Enqueue(message);
}
private void PrintMessage(string message)
{
this.Invoke((MethodInvoker)delegate
{
listBox_rows.Items.Add(message);
});
}
private void button_send_Click(object sender, EventArgs e)
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
library_dll.DoWork();
}).Start();
}
In DLL code, I use the callback method to report progress:
private CallBack callback;
public delegate void CallBack(string message);
public LibraryDLL() { }
public void Initialize(CallBack callback)
{
this.callback = callback;
}
public void DoWork()
{
callback("working...")
Thread.Sleep(500);
callback("working...")
Thread.Sleep(500);
callback("working...")
Thread.Sleep(500);
}
My problem is, that instead of string "working" appearing every 500ms, it appears 3 times after 1500ms (only after the Thread in which the DoWork method is running ends). I also tried the Invalidate()-Update()-Refresh() sequence in the Form's PrintMessage function, but without any effect.
Thanks for the advice!
EDIT1:
I modified the code to use the BackgroundWorker, however, the problem remains (nothing for 1500ms, than all 3 strings at once).
BackgroundWorker bck_worker;
public MainForm()
{
InitializeComponent();
library_dll = new LibraryDLL();
library_dll.Initialize(bck_worker);
bck_worker = new BackgroundWorker();
bck_worker.ProgressChanged += new ProgressChangedEventHandler(bckWorker_ProgressChanged);
bck_worker.WorkerReportsProgress = true;
bck_worker.WorkerSupportsCancellation = true;
}
private void bckWorker_DoWork(object sender, DoWorkEventArgs e)
{
library_dll.DoWork();
}
private void bckWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
PrintMessage((string)e.UserState);
}
private void button_send_Click(object sender, EventArgs e)
{
bck_worker.DoWork += new DoWorkEventHandler(bckWorker_DoWork);
bck_worker.RunWorkerAsync();
}
private void PrintMessage(string message)
{
listBox_rows.Items.Add(message);
}
And the DLL:
private BackgroundWorker bck_worker;
public LibraryDLL() { }
public void Initialize(BackgroundWorker bck_worker)
{
this.bck_worker = bck_worker;
}
public void DoWork()
{
bck_worker.ReportProgress(25, "working...");
Thread.Sleep(500);
bck_worker.ReportProgress(50, "working...");
Thread.Sleep(500);
bck_worker.ReportProgress(75, "working...");
Thread.Sleep(500);
}
EDIT2:
OK, I now tried to add the Invalidate-Update-Refresh sequence at the end of the PrintMessage function and it finaly works (with the BackgroundWorker approach)!
Use background worker and workers's report progress to update your UI: background worker doc

Only one active task at any time

I have several timers with different intervals. Tasks can be long running and they may overlap, but at any time I must be sure only one task is active. I have the following code with a bool variable which I am setting in event handlers:
public partial class SomeService : ServiceBase
{
private volatile bool IsActive;
private System.Timers.Timer Timer1;
private System.Timers.Timer Timer2;
protected override void OnStart(string[] args)
{
Timer1 = new System.Timers.Timer();
Timer1.Interval = ConfigurationManager.ImportEveryMinute1 * 60 * 1000;
Timer1.Elapsed += new System.Timers.ElapsedEventHandler(Timer1_Elapsed);
Timer1.Start();
Timer2 = new System.Timers.Timer();
Timer2.Interval = ConfigurationManager.ImportEveryMinute2 * 60 * 1000;
Timer2.Elapsed += new System.Timers.ElapsedEventHandler(Timer2_Elapsed);
Timer2.Start();
}
private void Timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (!IsActive)
{
IsActive = true;
DoSomeStuff1();
IsActive = false;
}
}
private void Timer2_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (!IsActive)
{
IsActive = true;
DoSomeStuff2();
IsActive = false;
}
}
}
Can you please tell me if volatile keyword is sufficient in my case or I should use locking or may be there is some better way for doing this?
u can use SemaphoreSlim.
private readonly SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);
private void Timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
semaphore.Wait();
DoSomeStuff1();
semaphore.Release();
}
private void Timer2_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
semaphore.Wait();
DoSomeStuff2();
semaphore.Release();
}
With your solution it can happen that
some timed operations could not processed, because the code doesn't stop and wait till IsActive get true.
it can happened that your two operations run on the same time. Because read and write on IsActive are two operations
I suggest the lock solution.
private static object LockObj = new object();
private void Timer2_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
lock(LockObj) { /* ... */ }
}
Not at all, on the contrary, using volatile just ensures that when having multiple threads, each of them will always see the latest value. It doesn't help in synchronizing between the threads.
The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times.
The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock statement to serialize access.
Imagine that both threads arrive at the
if (!IsActive)
They both see the latest value (false).
One advances, then the other. Now they are both inside.
If you want to thread synchronization, you'll have to use some sort of locking mechanism like lock.
Notice that with your implementation (event if it worked) the threads are not waiting for each other, they simply exit if the other one is active.
You might want to check out dataflow, it might fit your needs better.
Replace your timers with something like this:
private void Timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
lock(IsActive)
{
DoSomeStuff1();
}
}
private void Timer2_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
lock(IsActive)
{
DoSomeStuff2();
}
}

Use a other Method in a static method

How can I use the method ChangeText in my static method timer_Elapsed?
public Load()
{
InitializeComponent();
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 1000;
// I can't transfer parameters here
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
//Its underlined in red. I need a object reference?
ChangeText();
}
public void ChangeText()
{
label1.Text = label1.Text + ".";
}
I don't see any reason why timer_Elapsed should be static. So simply remove it.
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
ChangeText(); //Its not underlined anymore, you have an object reference
}
Another way would be to make ChangeText static. But that won't work since you want to set a Label's Text, so you need an instance of the Form anyway.
As first, your method (timer_Elapsed) could not me static, in order to use an instance property (label1)
There is an other problem in your code: Timer create an other thread, an most of windows control properties can be modified only by UI thread. Your code will throw a CrossThreadException.
In order to resolve your problem , you should modify your code with this:
if(this.InvokeRequired) {
BeginInvoke(
new MethodInvoker(delegate { label.Text+="."; }));
} else {
label.Text+=".";
}
Regards
Make ChangeText a static method.
public static void ChangeText()
Only static methods are called from a static method,
Either make your ChangeText() method to static or make your time_Elapsed method to non-static
You cannot call instance methods in static ones without creating an instance first. You have to create an instance of the class this method belongs to. like below:
var instance = new Load();
instance.ChangeText();
Update:
As other answers suggested, you should reconsider defining timer_Elapsed as static.
Hi Can you try like below:
public Load()
{
InitializeComponent();
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 1000;
// I can't transfer parameters here
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
private delegate void ChangeLabel();
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
var ChangeLabel = new ChangeLabel(ChangeText);
this.BeginInvoke(ChangeLabel);
}
private void ChangeText()
{
label1.Text = label1.Text + ".";
}

Converting C# System.Timer to Threading.Timer

i have been using System.Timer to run a windows service but have come across the problem where the timer randomly doesnt fire. I checked it yesterday and it hadnt fired for over 2 hours when its meant to fire every 10 mins. I read this up on Google and apparently its a known problem, the answer being to change over to Threading.Timer. I havent used this before so was looking for some insight. My current code is as follows:
using System;
using System.Timers;
using System.ServiceProcess;
namespace Code
{
public partial class Service : ServiceBase
{
Timer timer = new Timer();
public Service()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 10000;
timer.Enabled = true;
}
protected override void OnStop()
{
timer.Enabled = false;
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
timer.Enabled = false;
// Run system code here
timer.Interval = 600000;
timer.Enabled = true;
}
}
}
Basically, this normally works fine. The system starts the timer and fires after 10 seconds. It stops the timer, does the job, resets the timer for 10 minutes and enables it. For the most part this always works, but as mentioned randomly decides to stop working, probably due to system resources etc.
If anyone can help me convert this into a Threading.Timer it would be appreciated.
Thanks,
Chris
Here's my best guess - not got time to test it, sorry :(
using System;
using System.Threading;
using System.ServiceProcess;
namespace Code
{
public partial class Service : ServiceBase
{
Timer timer;
AutoResetEvent autoEvent;
bool stopped = true;
public Service()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
stopped = false;
TimerCallback tcb = new TimerCallback(OnElapsedTime);
timer = new Timer(tcb, null, 10000, 600000);
}
protected override void OnStop()
{
stopped = true;
timer.Dispose();
}
private void OnElapsedTime(Object stateInfo)
{
if (stopped)
return;
// Run system code here
}
}
}
http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx
Scroll down to find the example.

How to call event before Environment.Exit()?

I have a console application in C#. If something goes wrong, I call Environment.Exit() to close my application. I need to disconnect from the server and close some files before the application ends.
In Java, I can implement a shutdown hook and register it via Runtime.getRuntime().addShutdownHook(). How can I achieve the same in C#?
You can attach an event handler to the current application domain's ProcessExit event:
using System;
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.ProcessExit += (s, e) => Console.WriteLine("Process exiting");
Environment.Exit(0);
}
}
Hook AppDomain events:
private static void Main(string[] args)
{
var domain = AppDomain.CurrentDomain;
domain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
domain.ProcessExit += new EventHandler(domain_ProcessExit);
domain.DomainUnload += new EventHandler(domain_DomainUnload);
}
static void MyHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
Console.WriteLine("MyHandler caught: " + e.Message);
}
static void domain_ProcessExit(object sender, EventArgs e)
{
}
static void domain_DomainUnload(object sender, EventArgs e)
{
}
I'd recommend wrapping the call to Environment.Exit() in your own method and using that throughout. Something like this:
internal static void MyExit(int exitCode){
// disconnect from network streams
// ensure file connections are disposed
// etc.
Environment.Exit(exitCode);
}

Categories

Resources