У меня есть простое событие, определенное с использованием шаблона агрегатора событий PRISM.
public class TestEvent : PubSubEvent
{
}
public static class PrismEvents
{
public static readonly IEventAggregator EventAggregator = new EventAggregator();
public static readonly TestEvent EventTest = EventAggregator.GetEvent<TestEvent>();
}
У меня есть класс подписчика, в котором это событие подписывается с помощью лямбда. Обратите внимание на использование локальной переменной (i) внутри кода подписки.
public class SubScriber
{
public SubScriber()
{
int i = 5;
PrismEvents.EventTest.Subscribe(() =>
{
Console.WriteLine("Event Fired");//not getting called
i = 10; //commenting this line will execute the subscription code
});
}
}
На стороне издателя создается подписчик, затем вызывается GC, а затем публикуется событие.
Код подписки не выполняется!
class Program
{
static void Main(string[] args)
{
new SubScriber();
GC.Collect(); //commenting this line will execute the subscription code
PrismEvents.EventTest.Publish();
Console.ReadKey();
}
}
Пара очков
Комментирование использования локальной переменной (i=10) устранит проблему. Код подписки будет выполняться, как и ожидалось.
Комментирование GC.collect решит проблему. Код подписки будет выполняться, как ожидалось
В чем причина такого поведения?
SubScriber
совершенно не имеет значения, но незахватывающее лямбда-выражение можно использовать повторно, следовательно, связать с создающим его кодом, который будет использовать один и тот же объект каждый раз, когда вы его выполняете, что предотвратит его сборку мусора. Напротив, лямбда-выражение, фиксирующее текущую переменнуюi
, должно создавать новый экземпляр каждый раз при выполнении кода. Следовательно, код не будет хранить ссылку на него, и его можно будет собрать сразу после этого. - person Holger   schedule 07.03.2019