Short intro: I have a windows service which monitors other applications and services if they are functional at various time intervals. The service uses one timer (System.Threading.Timer) for every monitored application (named as "monitor"). Different types of applications require different types of monitors, some work synchronously and others asynchronous (for example, those using HttpClient).
So I got to the point where I would need asynchronous calls in a timer. I have simplified the code to the limit so that I can post it here. It can be run directly into a console project. My problem is that this code has a very bizarre behavior, as more timers are introduced - the harder it runs until it does not respond at all (over 20 timers). Does not the monitor run time be exactly the delay set in asynchronous operation (100ms)?
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace TestMain
{
class TestMain
{
private static List<TestTimer> timers = new List<TestTimer>();
static void Main(string[] args)
{
for (int i = 0; i < 20; i++)
{
TestMain.timers.Add(new TestTimer(i));
}
Console.WriteLine("Press [Enter] to exit.");
Console.ReadLine();
}
public class TestTimer
{
public Int32 Id { get; private set; }
private Timer timer;
public TestTimer(Int32 id)
{
this.Id = id;
this.timer = new Timer(this.Test, null, 1000, 30 * 1000);
}
private void Test(Object state)
{
TestWorker t = new TestWorker(this.Id);
t.Run();
}
}
public class TestWorker
{
public Int32 Id { get; private set; }
private Stopwatch sw = new Stopwatch();
public TestWorker(Int32 id) { this.Id = id; }
public void Run()
{
this.RunAsync().Wait();
}
private async Task RunAsync()
{
this.Log(String.Format("Start[{0,2}]", this.Id));
this.sw.Restart();
await Task.Run(() => { System.Threading.Thread.Sleep(100); }).ConfigureAwait(false);
this.sw.Stop();
this.Log(String.Format(" End[{0,2}] Duration=[{1}]", this.Id, (Int32)this.sw.ElapsedMilliseconds));
}
private void Log(String text)
{
Console.WriteLine(String.Format("{0,20} {1}", DateTime.Now, text));
}
}
}
}
I attached a printscreen with a run. Console Printscreen