0

我的 MVC3 异步控制器有问题,当控制器异步方法运行时,我增加异步控制器并开始监听 backednd 事件

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

然后当后端事件触发时,我减少并取消订阅后端事件

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

这可行,但是如果控制器超时,则 eventAggregator 将持有对控制器的订阅(它是一个 Weakrefence 列表,但由于某种原因旧控制器没有被删除)并且当后端事件触发时,旧控制器将首先窃取事件并将事件出列这意味着当真正的控制器收到消息时,队列为空并且没有任何内容发送到视图,这也是内存泄漏,所以几分钟后我们将在弱引用列表中有很多控制器......我如何取消订阅超时时来自 eventtaggregator 的控制器?

编辑:事件聚合器的代码,我们对此代码进行了单元测试,证明没有内存泄漏。奇怪的是,如果我创建一个没有任何引用的空标准控制器,它的解构器也不会运行......我们使用 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);
    }
}
4

1 回答 1

1

您可以覆盖EndExecute方法:

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

要定义超时时间,您可以使用该[AsyncTimeout]属性。

于 2012-03-13T09:09:35.923 回答