2012-03-13 59 views
0

刪除事件偵聽器,我有一個MVC3 asynccontroller,問題當控制器ASYC方法運行我遞增asyncontroller,也開始聽backednd事件從異步控制器上超時

AsyncManager.OutstandingOperations.Increment(); 
eventAggregator.Subscribe(this); 

,然後在後端事件觸發我遞減和取消訂閱後端事件

AsyncManager.OutstandingOperations.Decrement(); 
eventAggregator.Unsubscribe(this); 

這工作,但如果控制器超時的eventAggregator將舉行簽約到控制器(它是一個Weakrefence列表但somereason老控制器無法刪除d)當一個後端事件觸發舊控制器將首先竊取事件,並且當真正的控制器得到消息時隊列爲空並且沒有任何信息被髮送到視圖時將這些事件出隊,這也是一個內存泄漏,所以我們將會Weakreference列表中的很多控制器都有幾分鐘的時間...當它超時時,我怎樣才能從eventaggregator中取消訂閱控制器?

編輯:代碼爲事件聚合器,我們有此代碼的單元測試,證明沒有內存泄漏。奇怪的是,如果我創建一個沒有任何引用的空標準控制器,它的解構器也不會運行......我們使用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); 
    } 
} 

回答

1

您可以覆蓋EndExecute方法:

protected override void EndExecute(IAsyncResult asyncResult) 
{ 
    try 
    { 
     base.EndExecute(asyncResult); 
    } 
    catch(TimeoutException ex) 
    { 
     // Clean up your references here 
    } 
} 

,並確定您可以使用[AsyncTimeout]屬性的超時時間。

+0

感謝的人,可能解決了問題,但不是症狀,由於某種原因MVC3不釋放引用控制器,是不是很奇怪? – Anders 2012-03-13 09:16:12

+0

@Anders,我想你知道,沒有顯示你的代碼,我幾乎無法得到一些幫助。看看你的問題:你已經顯示了兩行代碼,並提供了關於這個'eventAggregator'變量是什麼的信息,它是如何實現的......理想地把你的問題縮小到你可以在這裏發佈的樣本,哪些將允許我們重現您的問題。否則,我擔心它幾乎不可能幫助你。 – 2012-03-13 09:49:04

+0

對不起,請參閱編輯。您的解決方案有效,所以原來的問題實際上得到了解答 – Anders 2012-03-13 10:07:16