Утечка памяти и локальные переменные - PullRequest
2 голосов
/ 28 декабря 2011

У меня есть следующий метод (в RegionAdapter для призмы).

protected override void Adapt(IRegion region, DocumentPane regionTarget)
{
    region.Views.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs e)
    {
        OnViewsCollectionChanged(sender, e, region, regionTarget);
    };
}

Моя проблема заключается в том, что при подписке на событие таким образом у меня возникает утечка памяти.Но параметры region и regionTarget являются локальными переменными для Adapt.

Я попытался найти это, чтобы посмотреть, обрабатывает ли кто-то сценарий по-разному, но все MSDN и MVP используют этот подход с утечкой ...

Как мне справиться с этим, чтобы потом отписаться о событии?

РЕДАКТИРОВАТЬ:
Приведенный выше код является лишь примером, который, я думаю, ясно иллюстрирует проблему.
Фактический код, который теряет память, выглядит следующим образом:

private void OnViewsCollectionChanged(object sender, 
    NotifyCollectionChangedEventArgs e, IRegion region, 
    DocumentPane regionTarget)
{
    if (e.Action == NotifyCollectionChangedAction.Add)
    {
        //Add content panes for each associated view.
        foreach (object item in e.NewItems)
        {
            UIElement view = item as UIElement;

            if (view != null)
            {
                DockableContent newContentPane = new DockableContent();
                newContentPane.IsCloseable = true;
                newContentPane.HideOnClose = false;

                ScrollViewer sViewer = new ScrollViewer()
                {
                    Content = item,
                    HorizontalScrollBarVisibility = ScrollBarVisibility.Auto,
                    VerticalScrollBarVisibility = ScrollBarVisibility.Auto
                };
                newContentPane.Content = sViewer;

                //When contentPane is closed remove the associated region
                // (MEMORY LEAK)
                newContentPane.Closed += (contentPaneSender, args) =>
                {
                    DockableContent docker =
                        contentPaneSender as DockableContent;
                    ScrollViewer scroller = docker.Content as ScrollViewer;
                    region.Remove(scroller.Content);
                    IDisposable dispView = scroller.Content as IDisposable;
                    if (dispView != null) dispView.Dispose();
                    scroller.Content = null;
                };
                regionTarget.Items.Add(newContentPane);
                newContentPane.Activate();
            }
        }
    }
}

Спасибо,

Баб.

1 Ответ

0 голосов
/ 28 декабря 2011

Используйте конкретный метод вместо анонима.Например:

   private Region _region;
   DocumentPane _regionTarget
   protected override void Adapt(IRegion region, DocumentPane regionTarget)
    {
        _region = region;
        _regionTarget = regionTarget;
        region.Views.CollectionChanged += OnCollectionChanged;
    }

    private void OnCollectionChanged (object sender, NotifyCollectionChangedEventArgs e) 
    {
        OnViewsCollectionChanged(sender, e, _region, _regionTarget);
    }

    ...
    private void Unsubscribe() 
    {
      _region.Views.CollectionChanged -= OnCollectionChanged;
    }
...