Comportamento estranho com ações, variáveis locais e coleta de lixo no MVVM light Messenger
Estou tendo um problema muito estranho com oMessenger
sistema no MVVM Light. É difícil de explicar, então aqui está um pequeno programa que demonstra o problema:
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; }
}
}
}
Se você executar o aplicativo, esta é a saída do console:
First Message recieved by A
First Message received by B
Second Message received by B
Como você pode ver, a segunda mensagem nunca é recebida pelo destinatário A. No entanto, a única diferença entre B e A é uma linha: a instruçãovar x = target;
. Se você remover esta linha,A
recebe a segunda mensagem.
Além disso, se você removerGC.Collect();
entãoA
recebe a segunda mensagem. No entanto, isso apenas oculta o problema, pois em um programa real o coletor de lixo será executado automaticamente eventualmente.
Por que isso está acontecendo? Suponho que, de alguma forma, se a ação do destinatário se referir a uma variável por conter o escopo do método, ela vinculará a vida útil da ação a esse escopo, para que, uma vez fora do escopo, possa ser coletada como lixo. Não entendo por que isso é verdade. Também não entendo por que ações que não fazem referência a variáveis do escopo em que estão definidas não apresentam esse problema.
Alguém pode explicar o que está acontecendo aqui?