how to get a c# method to run on a timer? - c#

How can I get a C# method to run on a timer? I found this example online but the DoStuffOnTimer() method below is not getting hit:
public void DoStuff()
{
var intervalMs = 5000;
var timer = new Timer(intervalMs);
timer.Elapsed += new ElapsedEventHandler(DoStuffOnTimer);
timer.Enabled = true;
}
private void DoStuffOnTimer(object source, ElapsedEventArgs e)
{
//do stuff
}

Or if you don't need very precise timer you always can create it yourself:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Temp
{
internal class Program
{
// this is the `Timer`
private static async Task CallWithInterval(Action action, TimeSpan interval, CancellationToken token)
{
while (true)
{
await Task.Delay(interval, token);
if (token.IsCancellationRequested)
{
return;
}
action();
}
}
// your method which is called with some interval
private static void DoSomething()
{
Console.WriteLine("ding!");
}
// usage sample
private static void Main()
{
// we need it to add the ability to stop timer on demand at any time
var cts = new CancellationTokenSource();
// start Timer
var task = CallWithInterval(DoSomething, TimeSpan.FromSeconds(1), cts.Token);
// continue doing another things - I stubbed it with Sleep
Thread.Sleep(5000);
// if you need to stop timer, let's try it!
cts.Cancel();
// check out, it really stopped!
Thread.Sleep(2000);
}
}
}

using System;
using System.Timers;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Program thisone = new Program();
thisone.DoStuff();
Console.Read();
}
public void DoStuff()
{
var intervalMs = 5000;
Timer timer = new Timer(intervalMs);
timer.Elapsed += new ElapsedEventHandler(DoStuffOnTimer);
timer.Enabled = true;
}
private void DoStuffOnTimer(object source, ElapsedEventArgs e)
{
//do stuff
Console.WriteLine("Tick!");
}
}
}

Related

C# Previous object is overwritted when adding new object to list

When I am adding new Timer to _timers it is overwriting previous one.
Console.WriteLine(_timers.Count()); is always writing 1
string.Join<string>(", ", _timers.Select(x => x.Uuid)); is returning empty string.
Here is my code:
[Group("timer")]
public class TimerHandler : ModuleBase<SocketCommandContext>
{
private List<Timer> _timers = new List<Timer>();
[Command("new")]
public async Task NewTimer(string content, [Remainder] int delay)
{
Timer timer = new Timer(content, delay, Context.Channel);
_timers.Add(timer);
Console.WriteLine(_timers.Count());
await ReplyAsync("created new timer with id: " + timer.Uuid);
}
[Command("list")]
public async Task ListTimer()
{
string reply;
string reply = string.Join<string>(", ", _timers.Select(x => x.Uuid));
await ReplyAsync(reply);
}
}
At times like these, what I try to do is create a minimum reproducible sample that removes anything unrelated to the problem. You could use a quick console app like I did here or a Unit Test. What this seems to show is that your code works as far as is shown:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Timers;
namespace timer_list
{
class Program
{
static void Main(string[] args)
{
runAsync();
Console.ReadKey();
}
static async void runAsync()
{
var timerHandler = new TimerHandler();
for (int i = 0; i < 5; i++)
{
await timerHandler.NewTimer("unused");
}
}
public class TimerHandler // : ModuleBase<SocketCommandContext>
{
private List<Timer> _timers = new List<Timer>();
public async Task NewTimer(string content)
{
Timer timer = new Timer();
_timers.Add(timer);
Console.WriteLine(_timers.Count());
await Task.Delay(1);
}
public async Task ListTimer()
{
await Task.Delay(10);
}
}
}
}
This makes me wonder if you're making a new instance of TimerHandler every time you use it. If this is the case, try changing:
private List<Timer> _timers = new List<Timer>()
to
private static List<Timer> _timers = new List<Timer>()
and see if that helps!

Exiting from async infinite loops

I have initiated some async infinite loops in my WinForm application, but each time I am trying to break out of them, the program hangs up. I have read some similar topics where people suggested using CancellationTokens, but I am not able to adapt them to my needs. Here is the relevant part of my code.
static bool processStop = false;
static bool processStopped = false;
//Called once
private async void ProcessData()
{
while (!processStop)
{
await Task.Run
(
() =>
{
//Do stuff and call regular not async methods
}
);
}
processStopped = true;
}
//Button click handler to exit WinForm
btnExit.Click += (senders, args) =>
{
processStop = true;
//Programm hangs up here
while (!processStopped);
FormMain.Close();
}
Edited the code
The variables are static.
The Close method is the default Close() method for Forms.
The problem is that the call to Task.Run continues on the main thread. processStop = true; and while (!processStopped); execute synchronously one after the other. This doesn't let the ProcessData method continue its execution and a deadlock occures.
I see a couple of solutions:
Use ConfigureAwait(false) with Task.Run:
private async void ProcessData()
{
while (!processStop)
{
await Task.Run
(
() =>
{
//Do stuff and call regular not async methods
}
).ConfigureAwait(false);
}
processStopped = true;
}
This will cause the ProcessData to continue on a thread pool and you already use a thread pool by calling Task.Run, so it is not a great solution
Wrap the whole process in Task.Run:
static volatile bool processStop = false;
static volatile bool processStopped = false;
//Called once
private async void ProcessData()
{
await Task.Run(() =>
{
while (!processStop)
{
...
}
processStopped = true;
});
}
This would require changing the form of the method passed to work with the loop in it.
Make ProcessData a synchronous method to process CPU-intensive tasks and call it properly. CancellationToken would be the preferred way to cancel the task:
private void ProcessData(CancellationToken token)
{
while(!token.IsCancellationRequested)
{
// do work
}
}
And call it with this:
Task processingTask;
CancellationTokenSource cts;
void StartProcessing()
{
cts = new CancellationTokenSource();
processingTask = Task.Run(() => ProcessData(cts.Token), cts.Token);
}
btnExit.Click += async (senders, args) =>
{
cts.Cancel();
try
{
await processingTask;
}
finally
{
FormMain.Close();
}
}
If you want to spin a bunch of tasks without blocking you can do this:
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//Called once
private async Task ProcessData()
{
int count = 0;
while (true)
{
await Task.Run
(
() =>
{
this.Invoke(new Action(() => {
label2.Text = (count++).ToString();
label1.Text = DateTime.Now.ToString(); }));
Thread.Sleep(100);
}
);
}
Debugger.Break(); //you will never see this hit at all
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}
private async void button2_Click(object sender, EventArgs e)
{
await ProcessData();
}
}
}

How to stop the application from closing while timer is running

namespace Client
{
class Program
{
static TcpClient client = new TcpClient();
static bool isServerOn = false;
static void Main(string[] args)
{
Timer timer = new Timer(1000);
timer.Elapsed += Update;
timer.Enabled = true;
}
private static void Update(Object source, ElapsedEventArgs e)
{
try
{
client.Connect("127.0.0.1", 1233);
if (isServerOn) return;
isServerOn = true;
Console.WriteLine("Server is On");
} catch(Exception)
{
if (!isServerOn) return;
isServerOn = false;
Console.WriteLine("Server Is Off");
}
}
}
}
i got this code for my client and the timer dont run because the application close after i run it can someone tell me how to make the timer run and the application dont close at the same time
Well you can use a Console.ReadKey() or Console.ReadLine() method like below but you should actually make it a WindowsService application rather a normal console application
static void Main(string[] args)
{
Timer timer = new Timer(1000);
timer.Elapsed += Update;
timer.Enabled = true;
Console.ReadKey();
}
You can solve this using Tasks.
Try this or something like it:
static void Main(string[] args)
{
Task t = Task.Run(async () => {
do
{
Update();
await Task.Delay(1000);
} while (isServerOn);
});
t.Wait();
}

Monitoring processes with while(true) loop

Is it possible to optimise my console application? It uses up to 60% of CPU because of while(true) loop.
The idea is to kill Microsoft managment console (services) process every time it starts up. And to start/stop services - use pswrd and console.
public static void Main(string[] args)
{
Thread consoleInput = new Thread(_consoleInput);
consoleInput.Start();
killProcess();
}
static void _consoleInput(){
getPassword();
sendServiceCommands();
}
static void killProcess(){
while(true){
try{
System.Diagnostics.Process[] myProcs = System.Diagnostics.Process.GetProcessesByName("mmc");
myProcs[0].Kill();
}
catch(Exception e){}
}
}
You need System.Threading.Timer. Something like this:
public class Killer
{
protected const int timerInterval = 1000; // define here interval between ticks
protected Timer timer = new Timer(timerInterval); // creating timer
public Killer()
{
timer.Elapsed += Timer_Elapsed;
}
public void Start()
{
timer.Start();
}
public void Stop()
{
timer.Stop();
}
public void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
System.Diagnostics.Process[] myProcs = System.Diagnostics.Process.GetProcessesByName("mmc");
myProcs[0].Kill();
}
catch {}
}
}
...
public static void Main(string[] args)
{
Killer killer = new Killer();
Thread consoleInput = new Thread(_consoleInput);
_consoleInput.Start();
killer.Start();
...
// whenever you want you may stop your killer
killer.Stop();
}

How to execute specified task at the specified time

I am new to C# but java has method to execute specified task at the specified time so using c# how it doing
Timer t=new Timer();
TimerTask task1 =new TimerTask()
t.schedule(task1, 3000);
You can get a complete tutorial of how timer works in C# here : http://www.dotnetperls.com/timer
In Short:
using System;
using System.Collections.Generic;
using System.Timers;
public static class TimerExample // In App_Code folder
{
static Timer _timer; // From System.Timers
static List<DateTime> _l; // Stores timer results
public static List<DateTime> DateList // Gets the results
{
get
{
if (_l == null) // Lazily initialize the timer
{
Start(); // Start the timer
}
return _l; // Return the list of dates
}
}
static void Start()
{
_l = new List<DateTime>(); // Allocate the list
_timer = new Timer(3000); // Set up the timer for 3 seconds
//
// Type "_timer.Elapsed += " and press tab twice.
//
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
_timer.Enabled = true; // Enable it
}
static void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
_l.Add(DateTime.Now); // Add date on each timer event
}
}
Using Anonymous Methods and Object Initializer:
var timer = new Timer { Interval = 5000 };
timer.Tick += (sender, e) =>
{
MessageBox.Show(#"Hello world!");
};
Here is a sample:
public class Timer1
{
public static void Main()
{
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed+=new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 5 seconds.
aTimer.Interval=5000;
aTimer.Enabled=true;
Console.WriteLine("Press \'q\' to quit the sample.");
while(Console.Read()!='q');
}
// Specify what you want to happen when the Elapsed event is raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("Hello World!");
}
}
using System;
using System.Threading;
namespace ConsoleApplication6
{
class Program
{
public void TimerTask(object state)
{
//Do your task
Console.WriteLine("oops");
}
static void Main(string[] args)
{
var program = new Program();
var timer = new Timer(program.TimerTask,
null,
3000,
Timeout.Infinite);
Thread.Sleep(10000);
}
}
}

Categories