C# System.Timers.Timer array countdown - c#

static void Main()
{
int timersLength = 4;
int interval = 1000;
int[] timerNum = new int[timersLength];
Timer[] timers = new Timer[timersLength];
for (int i = 0; i < timersLength; i++)
{
timerNum[i] = i;
timers[i] = new Timer(interval);
//Console.WriteLine($"Timer {timerNum[i]} is running");
timers[i].Elapsed += (o, e) =>
{
Console.WriteLine($"Timer {timerNum[i]} is running");
};
}
foreach (Timer timer in timers)
timer.Start();
Console.ReadKey();
}
whenever I'm trying to make a countdown to the Timer array it gives an
"System.IndexOutOfRangeException: 'Index was outside the bounds of the array."
on the Elapsed line:
timers[i].Elapsed += (o, e) =>
{
Console.WriteLine($"Timer {timerNum[i]} is running");
};
The code seems fine but for some reason it gives this error.

If you don't want to create a class to store the name of the Timer next to it then you can simply create a Dictionary<Timer, string> collection for mapping.
Dictionary<Timer, string> timers = new Dictionary<Timer, string>(timersLength);
for (int i = 0; i < timersLength; i++)
{
var timer = new Timer(interval);
timers[timer] = $"Timer {i}";
timer.Elapsed += (sender, _) => Console.WriteLine($"{timers[(Timer)sender]} is running");
}
foreach (KeyValuePair<Timer, string> mapping in timers)
mapping.Key.Start();
The Elapsed event handler will be called by passing the sender object
The sender's type is object so you need to cast it to Timer
That object can be used to do the look up in the timers collection
Since yo don't use the EventArgs of the Elapsed I suggest to use the discard operator there to express your intent more clearly

Related

How do I make use of a parameter in a ElapsedEventHandler (Timer)?

List<System.Timers.Timer> myTimers = new List<System.Timers.Timer>();
private void startFunction()
{
for (var parameter = 0; parameter < list.Count; parameter++)
{
System.Timers.Timer timer = new System.Timers.Timer(TimeSpan.FromMinutes(10).TotalMilliseconds);
timer.Elapsed += new ElapsedEventHandler(someFunction);
timer.Start();
myTimers.Add(timer);
}
}
// without the int parameter this code works
public void someFunction(object sender, ElapsedEventArgs e, int parameter)
{
// some code that have to run over time
}
So on the someFunction method I used a parameter (int) and without it, this is working out fine. I just want to send a parameter through this function and with searching online and trying different methods it still does not work.
Anyone having knowledge on how to send a parameter using the function someFunction every 10 minutes?
Since parameter is just a local variable, you can create a lambda which captures this variable, and passes it to your someFunction method.
private void startFunction()
{
for (var parameter = 0; parameter < list.Count; parameter++)
{
var timer = new System.Timers.Timer(TimeSpan.FromMinutes((10)).TotalMilliseconds);
int parameterCopy = parameter;
timer.Elapsed += (o, e) => someFunction(o, e, parameterCopy);
timer.Start();
myTimers.Add(timer);
}
}
The parameterCopy is required because of this issue.

System.Timers.Timer Not Triggered On Time in CPU-Intensive Program

I have .Net framwork 4.7.2 application, which handles cpu-intensive workload.
It uses system.timers.timer, intend to force program timeout after x mins.
The timer sometimes is not able to trigger on time.
Any suggestion on making the timer work properly, without loosing workload efficiency?
Following is the code to demonstrate the issue.
The timer set to triggered every 5 secs, but result is not as expected, which is shown in screenshot.
Please note that size of taskCollection is not predictable.
class Program
{
static void Main(string[] args)
{
var taskCollection = new string[new Random().Next(10, 100)];
SetupTimer();
Parallel.ForEach(taskCollection
, new ParallelOptions { MaxDegreeOfParallelism = -1 }
, task =>
{
SlowTask();
}
);
}
static void SetupTimer()
{
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += (s_, e_) =>
{
OnTimedEvent(s_, e_);
};
aTimer.Interval = 5000;
aTimer.Enabled = true;
Console.WriteLine($"Timer has been started at {DateTime.Now}.");
}
static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine($"Timer has been triggered at {DateTime.Now}.");
}
static void SlowTask()
{
long nthPrime = FindPrimeNumber(10000000); //set higher value for more time
}
static long FindPrimeNumber(int n)
{
int count = 0;
long a = 2;
while (count < n)
{
long b = 2;
int prime = 1;
while (b * b <= a)
{
if (a % b == 0)
{
prime = 0;
break;
}
b++;
}
if (prime > 0)
{
count++;
}
a++;
}
return (--a);
}
}

Multiple BackgroundWorker not always competing

I need to do lots (over 100,000) of ADO writes to a MySQL database. If I do this one at a time it will take hours (not acceptable). So figured I could break them into batches of 20 writes at a time into BackgroundWorker. The problem is that while it writes all the records to the database it does not exit out of the method. This means the only way I am to know if the system was completed was by looking at the database.
The code that creates all the BackgroundWorker;
ObservableCollection<MyClass> mObj = new ObservableCollection<MyClass>();
int recordsPerWorker= 20;
int i = 0;
int loop = 1;
int nLoops = (int)Math.Ceiling((double)numItms / (double)recordsPerWorker);
int remain = numItms % recordsPerWorker;
foreach (var x in MyObject)
{
mObj.Add(x);
i++;
if (loop == nLoops)
recordsPerWorker = remain;
if (i == recordsPerWorker)
{
loop++;
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += AddWoker_DoWork;
worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
worker.RunWorkerAsync(mObj);
mObj = new ObservableCollection<MyClass>();
i = 0;
}
}
while (completeWorkers != nLoops)
{
}
Then Worker_RunWorkerCompleted being;
private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
completeWorkers++;
}
I have tried this method as well with the same results
I could be going around this all wrong, so please point me in a different direction.

Memory leak in anonymous function

TLDR;
Non-trivial memory leak, can be seen easily in Resharper. See minimal example below.
I'm seeing a memory leak in the following program but failing to see why.
The program sends pings to a number of hosts asynchronously and determines if at least one is ok. To do that, a method (SendPing()) that runs these async operations is repeatedly called which runs them in a background thread (it doesn't have to, but in the actual application SendPing() will be called by the main UI thread which shouldn't be blocked).
The task seems pretty trivial but I think the leak occurs due to the way I create lambdas inside the SendPing() method. The program can be changed to not use lambdas but I'm more interested in understanding what causes the leak here.
public class Program
{
static string[] hosts = { "www.google.com", "www.facebook.com" };
static void SendPing()
{
int numSucceeded = 0;
ManualResetEvent alldone = new ManualResetEvent(false);
ManualResetEvent[] handles = new ManualResetEvent[hosts.Length];
for (int i = 0; i < hosts.Length; i++)
handles[i] = new ManualResetEvent(false);
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (sender, args) =>
{
numSucceeded = 0;
Action<int, bool> onComplete = (hostIdx, succeeded) =>
{
if (succeeded) Interlocked.Increment(ref numSucceeded);
handles[hostIdx].Set();
};
for (int i = 0; i < hosts.Length; i++)
SendPing(i, onComplete);
ManualResetEvent.WaitAll(handles);
};
worker.RunWorkerCompleted += (sender, args) =>
{
Console.WriteLine("Succeeded " + numSucceeded);
BackgroundWorker bgw = sender as BackgroundWorker;
alldone.Set();
};
worker.RunWorkerAsync();
alldone.WaitOne();
worker.Dispose();
}
static void SendPing(int hostIdx, Action<int, bool> onComplete)
{
Ping pingSender = new Ping();
pingSender.PingCompleted += (sender, args) =>
{
bool succeeded = args.Error == null && !args.Cancelled && args.Reply != null && args.Reply.Status == IPStatus.Success;
onComplete(hostIdx, succeeded);
Ping p = sender as Ping;
p.Dispose();
};
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
PingOptions options = new PingOptions(64, true);
pingSender.SendAsync(hosts[hostIdx], 2000, buffer, options, hostIdx);
}
private static void Main(string[] args)
{
for (int i = 0; i < 1000; i++)
{
Console.WriteLine("Send ping " + i);
SendPing();
}
}
}
Resharper shows the leaks are due to uncollected closure objects (c__DisplayClass...).
From what I understand, there shouldn't be a leak because there are no circular references (as far as I see) and therefore GC should take of the leaks. I also call Dispose to release the thread (bgw) + sockets (Ping object) promptly. (Even if I didn't GC will clean them up eventually, won't it?)
Suggested changes from comments
Remove event handles before Disposing
Dispose ManualResetEvent
But the leak is still there!
Changed program:
public class Program
{
static string[] hosts = { "www.google.com", "www.facebook.com" };
static void SendPing()
{
int numSucceeded = 0;
ManualResetEvent alldone = new ManualResetEvent(false);
BackgroundWorker worker = new BackgroundWorker();
DoWorkEventHandler doWork = (sender, args) =>
{
ManualResetEvent[] handles = new ManualResetEvent[hosts.Length];
for (int i = 0; i < hosts.Length; i++)
handles[i] = new ManualResetEvent(false);
numSucceeded = 0;
Action<int, bool> onComplete = (hostIdx, succeeded) =>
{
if (succeeded) Interlocked.Increment(ref numSucceeded);
handles[hostIdx].Set();
};
for (int i = 0; i < hosts.Length; i++)
SendPing(i, onComplete);
ManualResetEvent.WaitAll(handles);
foreach (var handle in handles)
handle.Close();
};
RunWorkerCompletedEventHandler completed = (sender, args) =>
{
Console.WriteLine("Succeeded " + numSucceeded);
BackgroundWorker bgw = sender as BackgroundWorker;
alldone.Set();
};
worker.DoWork += doWork;
worker.RunWorkerCompleted += completed;
worker.RunWorkerAsync();
alldone.WaitOne();
worker.DoWork -= doWork;
worker.RunWorkerCompleted -= completed;
worker.Dispose();
}
static void SendPing(int hostIdx, Action<int, bool> onComplete)
{
Ping pingSender = new Ping();
PingCompletedEventHandler completed = null;
completed = (sender, args) =>
{
bool succeeded = args.Error == null && !args.Cancelled && args.Reply != null && args.Reply.Status == IPStatus.Success;
onComplete(hostIdx, succeeded);
Ping p = sender as Ping;
p.PingCompleted -= completed;
p.Dispose();
};
pingSender.PingCompleted += completed;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
PingOptions options = new PingOptions(64, true);
pingSender.SendAsync(hosts[hostIdx], 2000, buffer, options, hostIdx);
}
private static void Main(string[] args)
{
for (int i = 0; i < 1000; i++)
{
Console.WriteLine("Send ping " + i);
SendPing();
}
}
}
There is no memory leak. dotMemory that you use analyzes the snapshots and indeed, in the context of one snapshot the auto-generated class created by the compiler for the completed event handler will still be in memory. Rewrite your main application like this:
private static void Main(string[] args)
{
for (int i = 0; i < 200; i++)
{
Console.WriteLine("Send ping " + i);
SendPing();
}
Console.WriteLine("All done");
Console.ReadLine();
}
Run the profiler, allow the application to reach the point where it outputs "All done", wait a few seconds and take a new snapshot. You will see there is no longer any memory leak.
It is worth mentioning that the class generated by the compiler for the PingCompleted event handler (that is c_DisplayClass6) will linger in memory after the method static void SendPing(int hostIdx, Action<int, bool> onComplete) exits. What happens there is that when pingSender.PingCompleted += (sender, args) =>... is executed the pingSender instance will take a reference to c_DisplayClass6. During the call to pingSender.SendAsync, the framework will retain a reference to pingSender in order to deal with running the async method and its completion. The async method you initiate by calling pingSender.SendAsync still runs when method SendPing exits. Because of that pingSender will survive a little while longer, hence c_DisplayClass6 will survive a little while longer too. However, after the pingSender.SendAsync operation completes, the framework will release its references to pingSender. At this point both pingSender and c_DisplayClass6 become garbage collectable and eventually the garbage collector will collect them. You can see this if you take a last snapshot like I was mentioning above. In that snapshot dotMemory will no longer detect a leak.
ManualResetEvent implements Dispose(). You are instantiating a number of ManualResetEvents and never calling dispose.
When an object implements dispose you need to call it. If you do not call it, there'll quite likely be memory leaks. You should use using statements, and try finally to dispose objects Simarly you should also have a using statement around Ping.
EDIT: This may be useful....
When should a ManualResetEvent be disposed?
EDIT: As stated here...
https://msdn.microsoft.com/en-us/library/498928w2(v=vs.110).aspx
When you create objects that include unmanaged resources, you must
explicitly release those resources when you finish using them in your
app.
EDIT: As stated here...
https://msdn.microsoft.com/en-us/library/system.threading.manualresetevent(v=vs.100).aspx
Dispose() Releases all resources used by the current instance of the
WaitHandle class. (Inherited from WaitHandle.)
The ManualResetEvent has unmanaged resources associated with it, which is fairly typical of most of the classes in the .NET Framework libraries which implements IDisposable.
EDIT: Try using this...
public class Program
{
static string[] hosts = { "www.google.com", "www.facebook.com" };
static void SendPing()
{
int numSucceeded = 0;
using (ManualResetEvent alldone = new ManualResetEvent(false))
{
BackgroundWorker worker = null;
ManualResetEvent[] handles = null;
try
{
worker = new BackgroundWorker();
DoWorkEventHandler doWork = (sender, args) =>
{
handles = new ManualResetEvent[hosts.Length];
for (int i = 0; i < hosts.Length; i++)
handles[i] = new ManualResetEvent(false);
numSucceeded = 0;
Action<int, bool> onComplete = (hostIdx, succeeded) =>
{
if (succeeded) Interlocked.Increment(ref numSucceeded);
handles[hostIdx].Set();
};
for (int i = 0; i < hosts.Length; i++)
SendPing(i, onComplete);
ManualResetEvent.WaitAll(handles);
foreach (var handle in handles)
handle.Close();
};
RunWorkerCompletedEventHandler completed = (sender, args) =>
{
Console.WriteLine("Succeeded " + numSucceeded);
BackgroundWorker bgw = sender as BackgroundWorker;
alldone.Set();
};
worker.DoWork += doWork;
worker.RunWorkerCompleted += completed;
worker.RunWorkerAsync();
alldone.WaitOne();
worker.DoWork -= doWork;
worker.RunWorkerCompleted -= completed;
}
finally
{
if (handles != null)
{
foreach (var handle in handles)
handle.Dispose();
}
if (worker != null)
worker.Dispose();
}
}
}
static void SendPing(int hostIdx, Action<int, bool> onComplete)
{
using (Ping pingSender = new Ping())
{
PingCompletedEventHandler completed = null;
completed = (sender, args) =>
{
bool succeeded = args.Error == null && !args.Cancelled && args.Reply != null && args.Reply.Status == IPStatus.Success;
onComplete(hostIdx, succeeded);
Ping p = sender as Ping;
p.PingCompleted -= completed;
p.Dispose();
};
pingSender.PingCompleted += completed;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
PingOptions options = new PingOptions(64, true);
pingSender.SendAsync(hosts[hostIdx], 2000, buffer, options, hostIdx);
}
}
private static void Main(string[] args)
{
for (int i = 0; i < 1000; i++)
{
Console.WriteLine("Send ping " + i);
SendPing();
}
}
}

Wait with return statement until Timer elapsed

I have a method that returns a bool value, but should wait with returning the value until the System.Timers.Timer raises the elapsed event, because the value I want to return is set in the elapsed event of the timer.
public static bool RecognizePushGesture()
{
List<Point3D> shoulderPoints = new List<Point3D>();
List<Point3D> handPoints = new List<Point3D>();
shoulderPoints.Add(Mouse.shoulderPoint);
handPoints.Add(Mouse.GetSmoothPoint());
Timer dt = new Timer(1000);
bool click = false;
dt.Elapsed += (o, s) =>
{
shoulderPoints.Add(Mouse.shoulderPoint);
handPoints.Add(Mouse.GetSmoothPoint());
double i = shoulderPoints[0].Z - handPoints[0].Z;
double j = shoulderPoints[1].Z - handPoints[1].Z;
double k = j - i;
if (k >= 0.04)
{
click = true;
dt.Stop();
}
};
dt.Start();
//should wait with returning the value until timer raises elapsed event
return click;
}
Thanks, Tim
Use AutoResetEvent
public static bool RecognizePushGesture()
{
AutoResetEvent ar = new AutoResetEvent(false);
List<Point3D> shoulderPoints = new List<Point3D>();
List<Point3D> handPoints = new List<Point3D>();
shoulderPoints.Add(Mouse.shoulderPoint);
handPoints.Add(Mouse.GetSmoothPoint());
Timer dt = new Timer(1000);
bool click = false;
dt.Elapsed += (o, s) =>
{
shoulderPoints.Add(Mouse.shoulderPoint);
handPoints.Add(Mouse.GetSmoothPoint());
double i = shoulderPoints[0].Z - handPoints[0].Z;
double j = shoulderPoints[1].Z - handPoints[1].Z;
double k = j - i;
if (k >= 0.04)
{
click = true;
dt.Stop();
}
ar.Set();
};
dt.Start();
//should wait with returning the value until timer raises elapsed event
ar.WaitOne();
return click;
}

Categories

Resources