A volte gli utenti desiderano programmare un ampio set di timer e non vogliono gestire i riferimenti a quei timer.
Nel caso in cui l'utente non faccia riferimento a un timer, il timer può essere raccolto dal GC prima dell'esecuzione.
Ho creato il Timer classe a fungere da supporto per luogo timer appena creati:Perdita di memoria attorno al delegato del timer
static class Timers
{
private static readonly ILog _logger = LogManager.GetLogger(typeof(Timers));
private static readonly ConcurrentDictionary<Object, Timer> _timers = new ConcurrentDictionary<Object, Timer>();
/// <summary>
/// Use this class in case you want someone to hold a reference to the timer.
/// Timer without someone referencing it will be collected by the GC even before execution.
/// </summary>
/// <param name="dueTime"></param>
/// <param name="action"></param>
internal static void ScheduleOnce(TimeSpan dueTime, Action action)
{
if (dueTime <= TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException("dueTime", dueTime, "DueTime can only be greater than zero.");
}
Object obj = new Object();
Timer timer = new Timer(state =>
{
try
{
action();
}
catch (Exception ex)
{
_logger.ErrorFormat("Exception while executing timer. ex: {0}", ex);
}
finally
{
Timer removedTimer;
if (!_timers.TryRemove(obj, out removedTimer))
{
_logger.Error("Failed to remove timer from timers");
}
else
{
removedTimer.Dispose();
}
}
});
if (!_timers.TryAdd(obj, timer))
{
_logger.Error("Failed to add timer to timers");
}
timer.Change(dueTime, TimeSpan.FromMilliseconds(-1));
}
}
Se non dispongo il timer rimosso, risulta con una perdita di memoria.
Sembra che qualcuno abbia un riferimento al delegato del Timer dopo che il timer è stato rimosso dalla raccolta _timers
.
La domanda è: perché ricevo una perdita di memoria se non dispongo il timer?
Forse non capisco quello che stai chiedendo, perché suona come vi state chiedendo perché qualcosa si comporta male quando si maltrattano esso ... –
Capisco che la documentazione indichi che i componenti devono essere smaltiti. Sono ancora curioso di sapere cosa impedisce al GC di raccogliere il timer e il delegato dato senza chiamare il metodo di smaltimento. –