Func<T> 回调会导致内存泄漏吗?
Does Func<T> callbacks can cause memory leak?
每个人都知道永远不会为 invocationList 删除的事件处理程序会导致 C# 中的内存泄漏。
我的问题是,如果我们使用 Func 作为回调,我们会发生内存泄漏吗? (因此仅支持一个订阅者)
以下面的例子为例(复制并粘贴到控制台应用程序):
class Program
{
static void Main(string[] args)
{
var m = new Manager();
var c1 = new Channel();
m.Add(c1);
Console.WriteLine("m = {0}",GC.GetTotalMemory(true));
Console.ReadLine();
m.Remove(c1);
Console.WriteLine("m = {0}", GC.GetTotalMemory(true));
Console.ReadLine();
}
}
public class Manager
{
List<Channel> channels = new List<Channel>();
public void Add(Channel c)
{
channels.Add(c);
c.OnTick = OnTick;
c.Start();
}
public void Remove(Channel c)
{
channels.Remove(c);
//do we have a memory leak at this point?
//does c1 still pointing to Manager func and cannot be GCed?
c.Stop();
}
private Task OnTick(int i)
{
Console.WriteLine(i);
return Task.FromResult(0);
}
}
public class Channel
{
public Func<int, Task> OnTick;
Random r = new Random();
private System.Timers.Timer aTimer;
public Channel()
{
OnTick = i => Task.FromResult(r.Next());
}
public void Start()
{
aTimer = new System.Timers.Timer(1000);
aTimer.Elapsed += (sender, args) => OnTick(r.Next());
// Have the timer fire repeated events (true is the default)
aTimer.AutoReset = true;
// Start the timer
aTimer.Enabled = true;
}
public void Stop()
{
aTimer.Dispose();
}
}
//do we have a memory leak at this point?
没有。在 ANTS Memory Profiler 上对此进行了测试以验证这一点。
//does c1 still pointing to Manager func and cannot be GCed?
Manager
是订阅者,Channel
是发布者。如果没有对 Channel 实例的引用并且它是符合条件的 GC。
每个人都知道永远不会为 invocationList 删除的事件处理程序会导致 C# 中的内存泄漏。 我的问题是,如果我们使用 Func 作为回调,我们会发生内存泄漏吗? (因此仅支持一个订阅者)
以下面的例子为例(复制并粘贴到控制台应用程序):
class Program
{
static void Main(string[] args)
{
var m = new Manager();
var c1 = new Channel();
m.Add(c1);
Console.WriteLine("m = {0}",GC.GetTotalMemory(true));
Console.ReadLine();
m.Remove(c1);
Console.WriteLine("m = {0}", GC.GetTotalMemory(true));
Console.ReadLine();
}
}
public class Manager
{
List<Channel> channels = new List<Channel>();
public void Add(Channel c)
{
channels.Add(c);
c.OnTick = OnTick;
c.Start();
}
public void Remove(Channel c)
{
channels.Remove(c);
//do we have a memory leak at this point?
//does c1 still pointing to Manager func and cannot be GCed?
c.Stop();
}
private Task OnTick(int i)
{
Console.WriteLine(i);
return Task.FromResult(0);
}
}
public class Channel
{
public Func<int, Task> OnTick;
Random r = new Random();
private System.Timers.Timer aTimer;
public Channel()
{
OnTick = i => Task.FromResult(r.Next());
}
public void Start()
{
aTimer = new System.Timers.Timer(1000);
aTimer.Elapsed += (sender, args) => OnTick(r.Next());
// Have the timer fire repeated events (true is the default)
aTimer.AutoReset = true;
// Start the timer
aTimer.Enabled = true;
}
public void Stop()
{
aTimer.Dispose();
}
}
//do we have a memory leak at this point?
没有。在 ANTS Memory Profiler 上对此进行了测试以验证这一点。
//does c1 still pointing to Manager func and cannot be GCed?
Manager
是订阅者,Channel
是发布者。如果没有对 Channel 实例的引用并且它是符合条件的 GC。