Last active
September 10, 2018 14:57
-
-
Save inwenis/d8544192df76d6fe3fd4075f310119b4 to your computer and use it in GitHub Desktop.
When your Timer is GC.Collected its action will never fire
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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