У меня проблема с асинхронным контроллером MVC3. Когда асинхронный метод контроллера запускается, я увеличиваю асинхронный контроллер и также начинаю слушать события бэкэнда
AsyncManager.OutstandingOperations.Increment();
eventAggregator.Subscribe(this);
А затем, когда запускается внутреннее событие, я уменьшаю и отписываюськ внутренним событиям
AsyncManager.OutstandingOperations.Decrement();
eventAggregator.Unsubscribe(this);
Это работает, но если время ожидания контроллера истекло, eventAggregator будет хранить подписку на контроллер (это список Weakrefence, но по какой-то причине старый контроллер не удаляется) и когда событие внутреннего события запускаетсястарый контроллер сначала украдет событие и выведет из него события, то есть, когда реальный контроллер получит сообщение, очередь пуста и ничто не отправлено в представление, также это утечка памяти, поэтому в списке Weakreference у нас будет много контроллеров послепару минут ... Как я могу отписать контроллер от Eventaggregator, когда он истекает?
edit: Код для агрегатора событий, у нас есть модульные тесты для этого кода, которые доказывают отсутствие утечек памяти.Странно то, что если я создаю пустой стандартный контроллер без каких-либо ссылок на что-либо, его деконструктор тоже не запускается ... Мы используем IoC (Ninject), может ли это быть проблемой?
public class EventAggregator : IEventAggregator
{
private readonly IConfig config;
private readonly WeakReferenceList<object> subscribers = new WeakReferenceList<object>();
public EventAggregator(IConfig config)
{
this.config = config;
}
public void Subscribe(object subsriber)
{
subscribers.Add(subsriber);
}
public void Unsubscribe(object subscriber)
{
subscribers.Remove(subscriber);
}
public void Publish<T>(T message) where T : class
{
var lookupType = typeof (IHandle<T>);
if (config.EnableEventAggregator)
subscribers.Where(lookupType.IsInstanceOfType)
.Select(s => s as IHandle<T>)
.ForEach(s => s.Handle(message));
}
}
public class WeakReferenceList<T> : ICollection<T> where T : class
{
private readonly List<WeakReference> list = new List<WeakReference>();
public IEnumerator<T> GetEnumerator()
{
return GetAlive().Select(item => item.Target as T).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(T item)
{
CleanDeadReferences();
list.Add(new WeakReference(item));
}
public void Clear()
{
list.Clear();
}
public bool Contains(T item)
{
return GetAlive().Any(weakItem => weakItem.Target.Equals(item));
}
public void CopyTo(T[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public bool Remove(T item)
{
CleanDeadReferences();
return list.RemoveAll(weakItem => weakItem.Target.Equals(item)) > 0;
}
public int Count
{
get { return GetAlive().Count(); }
}
public bool IsReadOnly
{
get { return false; }
}
public int IndexOf(T item)
{
var weakItem = list.First(x => x.Target == item);
return list.IndexOf(weakItem);
}
public void Insert(int index, T item)
{
CleanDeadReferences();
list.Insert(index, new WeakReference(item));
}
private IEnumerable<WeakReference> GetAlive()
{
return list.ToList().Where(item => item.IsAlive);
}
private void CleanDeadReferences()
{
list.RemoveAll(item => !item.IsAlive);
}
}