Execute specified function every X seconds

I have a Windows Forms application written in C#. The following function checks whenever printer is online or not:

public void isonline()
{
PrinterSettings settings = new PrinterSettings();
if (CheckPrinter(settings.PrinterName) == "offline")
{
pictureBox1.Image = pictureBox1.ErrorImage;
}
}

and updates the image if the printer is offline. Now, how can I execute this function isonline() every 2 seconds so when I unplug the printer, the image displayed on the form (pictureBox1) turns into another one without relaunching the application or doing a manual check? (eg. by pressing "Refresh" button which runs the isonline() function)

200252 次浏览

Use System.Windows.Forms.Timer.

private Timer timer1;
public void InitTimer()
{
timer1 = new Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval = 2000; // in miliseconds
timer1.Start();
}


private void timer1_Tick(object sender, EventArgs e)
{
isonline();
}

You can call InitTimer() in Form1_Load().

You can do this easily by adding a Timer to your form (from the designer) and setting it's Tick-function to run your isonline-function.

The most beginner-friendly solution is:

Drag a Timer from the Toolbox, give it a Name, set your desired Interval, and set "Enabled" to True. Then double-click the Timer and Visual Studio (or whatever you are using) will write the following code for you:

private void wait_Tick(object sender, EventArgs e)
{
refreshText(); // Add the method you want to call here.
}

No need to worry about pasting it into the wrong code block or something like that.

Threaded:

    /// <summary>
/// Usage: var timer = SetIntervalThread(DoThis, 1000);
/// UI Usage: BeginInvoke((Action)(() =>{ SetIntervalThread(DoThis, 1000); }));
/// </summary>
/// <returns>Returns a timer object which can be disposed.</returns>
public static System.Threading.Timer SetIntervalThread(Action Act, int Interval)
{
TimerStateManager state = new TimerStateManager();
System.Threading.Timer tmr = new System.Threading.Timer(new TimerCallback(_ => Act()), state, Interval, Interval);
state.TimerObject = tmr;
return tmr;
}

Regular

    /// <summary>
/// Usage: var timer = SetInterval(DoThis, 1000);
/// UI Usage: BeginInvoke((Action)(() =>{ SetInterval(DoThis, 1000); }));
/// </summary>
/// <returns>Returns a timer object which can be stopped and disposed.</returns>
public static System.Timers.Timer SetInterval(Action Act, int Interval)
{
System.Timers.Timer tmr = new System.Timers.Timer();
tmr.Elapsed += (sender, args) => Act();
tmr.AutoReset = true;
tmr.Interval = Interval;
tmr.Start();


return tmr;
}
using System;
using System.Timers;
namespace SnirElgabsi
{
class Program
{
private static Timer timer1;
static void Main(string[] args)
{
timer1 = new Timer(); //new Timer(1000);
timer1.Elpased += (sender,e) =>
{
MyFoo();
}
timer1.Interval = 1000;//miliseconds
timer1.Start();
       

Console.WriteLine("press any key to stop");
Console.ReadKey();
}


private static void MyFoo()
{
Console.WriteLine(string.Format("{0}", DateTime.Now));
}
}
}

Things have changed a lot with time. You can use the solution below:

static void Main(string[] args)
{
var timer = new Timer(Callback, null, 0, 2000);


//Dispose the timer
timer.Dispose();
}
static void Callback(object? state)
{
//Your code here.
}

.NET 6 has added the PeriodicTimer class.

var periodicTimer= new PeriodicTimer(TimeSpan.FromSeconds(1));
while (await periodicTimer.WaitForNextTickAsync())
{
// Place function in here..
Console.WriteLine("Printing");
}

You can run it in the background with this:

async Task RunInBackground(TimeSpan timeSpan, Action action)
{
var periodicTimer = new PeriodicTimer(timeSpan);
while (await periodicTimer.WaitForNextTickAsync())
{
action();
}
}


RunInBackground(TimeSpan.FromSeconds(1), () => Console.WriteLine("Printing"));

The main advantage PeriodicTimer has over a Timer.Delay loop is best observed when executing a slow task.

using System.Diagnostics;


var stopwatch = Stopwatch.StartNew();
// Uncomment to run this section
//while (true)
//{
//    await Task.Delay(1000);
//    Console.WriteLine($"Delay Time: {stopwatch.ElapsedMilliseconds}");
//    await SomeLongTask();
//}


//Delay Time: 1007
//Delay Time: 2535
//Delay Time: 4062
//Delay Time: 5584
//Delay Time: 7104


var periodicTimer = new PeriodicTimer(TimeSpan.FromMilliseconds(1000));
while (await periodicTimer.WaitForNextTickAsync())
{
Console.WriteLine($"Periodic Time: {stopwatch.ElapsedMilliseconds}");
await SomeLongTask();
}


//Periodic Time: 1016
//Periodic Time: 2027
//Periodic Time: 3002
//Periodic Time: 4009
//Periodic Time: 5018


async Task SomeLongTask()
{
await Task.Delay(500);
}

PeriodicTimer will attempt to invoke every n * delay seconds, whereas Timer.Delay will invoke every n * (delay + time for method to run) seconds, causing execution time to gradually move out of sync.