Reputation: 359
Can anyone explain what happens here?
delegate void TestDelegate(string val);
class Program
{
static void Main(string[] args)
{
Test p = new Test();
string s = "Main";
TestDelegate strongRef = (val) =>
{
Console.WriteLine(val + ": " + s);
};
p.AssignLambda(strongRef);
while (true)
{
p.CallLambda();
Thread.Sleep(1000);
System.GC.Collect();
}
}
}
class Test
{
WeakReference _ref;
internal void AssignLambda(TestDelegate del)
{
_ref = new WeakReference(del);
}
internal void CallLambda()
{
TestDelegate del = _ref.Target as TestDelegate;
if (del != null)
{
del("Delegate Alive");
}
else
{
Console.WriteLine("Delegate Dead");
}
}
}
I am expecting "Delegate Alive: Main" to get printed continuously. But I get "Delegate Dead" printed continuously.
Note: I compile this as 64 bit application. It works fine as expected if I compile it as 32 bit Application.
Compiler: VS 2012, Target Framework: .NET 4.0, OS: Win 7 64 bit professional
Upvotes: 1
Views: 752
Reputation: 169113
Based on this code, the delegate object should be collected when you call System.GC.Collect()
, because there are no strong references to the delegate object at that time -- the only reference is a weak one, which does not prevent collection.
It is possible that the difference in behavior is due to different JIT engines between the 32-bit and 64-bit CLRs; it is possible (and very likely) that a reference to the delegate object remains in a CPU register when using the 32-bit JIT, but not when using the 64-bit JIT. This would explain why the object is always collected in one case but not in another.
This should be considered an implementation detail. As the GC is not guaranteed to be deterministic, your code should not rely on particular behavior from the GC.
Upvotes: 3