사용자가 많은 타이머 세트를 예약하려고하고 해당 타이머에 대한 참조를 관리하지 않으려는 경우가 있습니다.
사용자가 타이머를 참조하지 않는 경우 타이머가 실행되기 전에 GC에 의해 타이머가 수집 될 수 있습니다.
나는 새로 만든 타이머에 대한 자리 표시 자 역할을하는 클래스 타이머를 생성 : 나는 제거 타이머를 폐기하지 않으면타이머 위임시 메모리 누수
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));
}
}
, 그것은 메모리 누수로 발생합니다.
타이머가 _timers
컬렉션에서 제거 된 후 누군가가 타이머 대리자에 대한 참조를 보유하고있는 것처럼 보입니다.
질문 : 왜 타이머를 처리하지 않으면 메모리 누수가 발생합니까?
어쩌면 내가, 당신이 요구하는지 이해하지 않는다 ... –
설명서에 구성 요소가 폐기되어야한다고 나와 있음을 이해합니다. 여전히 GC에서 dispose 메서드를 호출하지 않고 타이머 및 주어진 대리자를 수집하지 못하게하는 것이 궁금합니다. –