Странное поведение с действиями, локальными переменными и сборкой мусора в MVVM light Messenger
У меня действительно странная проблема сMessenger
система в МВВМ Лайт. Это сложно объяснить, поэтому вот небольшая программа, которая демонстрирует проблему:
using System;
using GalaSoft.MvvmLight.Messaging;
namespace TestApp
{
class Program
{
static void Main(string[] args)
{
var prog = new Program();
var recipient = new object();
prog.RegisterMessageA(recipient);
prog.RegisterMessageB(recipient);
prog.SendMessage("First Message");
GC.Collect();
prog.SendMessage("Second Message");
}
public void RegisterMessageA(object target)
{
Messenger.Default.Register(this, (Message msg) =>
{
Console.WriteLine(msg.Name + " recieved by A");
var x = target;
});
}
public void RegisterMessageB(object target)
{
Messenger.Default.Register(this, (Message msg) =>
{
Console.WriteLine(msg.Name + " received by B");
});
}
public void SendMessage(string name)
{
Messenger.Default.Send(new Message { Name = name });
}
class Message
{
public string Name { get; set; }
}
}
}
Если вы запустите приложение, это вывод консоли:
First Message recieved by A
First Message received by B
Second Message received by B
Как вы можете видеть, второе сообщение никогда не принимается получателем A. Однако единственная разница между B и A состоит в одной строке: операторvar x = target;
, Если вы удалите эту строку,A
получает второе сообщение.
Кроме того, если вы удалитеGC.Collect();
затемA
получает второе сообщение. Однако это только скрывает проблему, так как в реальной программе сборщик мусора автоматически запускается в конце концов.
Почему это происходит? Я предполагаю, что каким-то образом, если действие получателя ссылается на переменную из области действия содержащего его метода, оно связывает время жизни действия с этой областью, чтобы после выхода из области его можно было собрать мусором. Я не понимаю, почему это вообще. Я также не понимаю, почему действия, которые не ссылаются на переменные из области, в которой они определены, не имеют этой проблемы.
Кто-нибудь может объяснить, что здесь происходит?