Skip to content

Instantly share code, notes, and snippets.

@inwenis
Last active September 10, 2018 14:57
Show Gist options
  • Save inwenis/d8544192df76d6fe3fd4075f310119b4 to your computer and use it in GitHub Desktop.
Save inwenis/d8544192df76d6fe3fd4075f310119b4 to your computer and use it in GitHub Desktop.
When your Timer is GC.Collected its action will never fire
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
// This piece of code shows that if you do not assign a variable to your Timer (like in Runner.ExecuteWithTimeout_NotWorking)
// your timer may be Garbage Collected before its action fires.
// In case of the code below this will result in the Tasks running for ever.
// Calling GC.Collect() forces Garbage Collection to fake a real aplicaiton and long running Tasks.
// use: var tasks = Enumerable.Range(1, 10).Select(x => new Runner().ExecuteWithTimeout_NotWorking()).ToArray();
// to create 10 Tasks which never end
// use: var tasks = Enumerable.Range(1, 10).Select(x => new Runner().ExecuteWithTimeout()).ToArray();
// to see how it should be working correctly
class Program
{
public static ConcurrentBag<int> bag = new ConcurrentBag<int>();
static void Main(string[] args)
{
Task.Run(async () =>
{
// var tasks = Enumerable.Range(1, 10).Select(x => new Runner().ExecuteWithTimeout()).ToArray(); // this is how it should be done
var tasks = Enumerable.Range(1, 10).Select(x => new Runner().ExecuteWithTimeout_NotWorking()).ToArray(); // this will be running for ever
while (true)
{
GC.Collect();
Thread.Sleep(500);
Console.WriteLine("currently there are: " + bag.Count + " tasks running");
}
}).GetAwaiter().GetResult();
}
}
public class Runner
{
public async Task ExecuteWithTimeout()
{
Program.bag.Add(1);
bool kill = false;
var timer = new Timer(_ => {
Console.WriteLine("timer action!");
kill = true;
}, null, 5 * 1000, int.MaxValue);
Console.WriteLine("waiting for exit of task");
while (!kill)
{
await Task.Delay(500);
}
Console.WriteLine("ended Task");
Program.bag.TryTake(out int x);
timer.Dispose();
}
public async Task ExecuteWithTimeout_NotWorking()
{
Program.bag.Add(1);
bool kill = false;
new Timer(_ => {
Console.WriteLine("timer action!");
kill = true;
}, null, 5 * 1000, int.MaxValue);
Console.WriteLine("waiting for exit of task");
while (!kill)
{
await Task.Delay(500);
}
Console.WriteLine("ended Task");
Program.bag.TryTake(out int x);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment