DispatherTimer可能会引起内存泄漏

为什么System.Windows.Threading.DispatherTimer可能会引起内存泄漏?

关键点:事件导致内存泄漏

描述

当不正确使用DispatherTimer时,可能会导致内存泄漏。例子:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        MLClass cl = new MLClass();
    }
}
public class MLClass
{
    DispatcherTimer dt;
    public MLClass()
    {
        dt = new DispatcherTimer();
        dt.Interval = TimeSpan.FromSeconds(1);
        dt.Tick += dt_Tick;
        dt.Start();
    }
    void dt_Tick(object sender, EventArgs e)
    {
        //throw new NotImplementedException();
    }
}

分析

DispatcherTimer源码:

	public void Start()
	{
		lock (this._instanceLock)
		{
			if (!this._isEnabled)
			{
				this._isEnabled = true;
				this.Restart();
			}
		}
	}
	private void Restart()
	{
		lock (this._instanceLock)
		{
			if (this._operation == null)
			{
				this._operation = this._dispatcher.BeginInvoke(DispatcherPriority.Inactive, new DispatcherOperationCallback(this.FireTick), null);
				this._dueTimeInTicks = Environment.TickCount + (int)this._interval.TotalMilliseconds;
				if (this._interval.TotalMilliseconds == 0.0 && this._dispatcher.CheckAccess())
				{
					this.Promote();
				}
				else
				{
					this._dispatcher.AddTimer(this);
				}
			}
		}
	}

Dispatcher源码:

internal void AddTimer(DispatcherTimer timer)
{
	lock (this._instanceLock)
	{
		if (!this._hasShutdownFinished)
		{
			this._timers.Add(timer);
			this._timersVersion += 1L;
		}
	}
	this.UpdateWin32Timer();
}

相互之间引用:
Dispatcher(通过_timers)--> DispatherTimer(通过Tick)--> MLClass cl
所以当DispatherTimer不需要时须取消订阅。

问题

需不需要DispatherTimer.Stop()?

看代码:

	public void Stop()
	{
		bool flag = false;
		lock (this._instanceLock)
		{
			if (this._isEnabled)
			{
				this._isEnabled = false;
				flag = true;
				if (this._operation != null)
				{
					this._operation.Abort();
					this._operation = null;
				}
			}
		}
		if (flag)
		{
			this._dispatcher.RemoveTimer(this);
		}
	}

    internal void RemoveTimer(DispatcherTimer timer)
	{
		lock (this._instanceLock)
		{
			if (!this._hasShutdownFinished)
			{
				this._timers.Remove(timer);
				this._timersVersion += 1L;
			}
		}
		this.UpdateWin32Timer();
	}

参考及引用

  1. 大内老A-[转]如何解决事件导致的Memory Leak问题:Weak Event Handlers
  2. 大内老A-事件(Event),绝大多数内存泄漏(Memory Leak)的元凶[上篇]

posted on 2017-02-22 14:43  CX_  阅读(241)  评论(0编辑  收藏  举报

导航