繁体   English   中英

WPF框架在后台线程中使用Dispatcher.CurrentDispatcher,导致内存泄漏

[英]WPF framework using Dispatcher.CurrentDispatcher in background thread, causing memory leak

我正在使用 WPF CollectionView 并且我正在后台线程中设置过滤器,因为应用此过滤器需要很长时间。

设置这个过滤器会触发 CollectionView 的ScheduleMapCleanup () 方法(所以 WPF 框架代码我无法更改)。 在此方法中,使用了 Dispatcher.CurrentDispatcher.BeginInvoke。

但是,因为这是在后台线程中执行的,所以这个Action永远不会被执行(这个线程的Dispatcher永远不会启动),导致内存泄漏:Dispatcher保留了对CollectionView的引用。

我该如何解决这个问题? 在 UI 线程中设置过滤器不是一个选项。

我可以自己启动 Dispatcher 吗? 如果是这样,我该怎么做(Dispatcher.Run 停止一切)?

当我需要从后台任务更新 UI 线程上的一些控件和绑定时,我会使用它:

Application.Current.Dispatcher.Invoke(
    DispatcherPriority.Loaded,
    new Action(() => {

        // Code here

    })
);

如果不是这样,你可以更具体地说明你想在你的 UI 线程上做什么

从后台线程访问当前调度程序不会为您提供 UI 调度程序,它为后台线程提供了一个新的调度程序。

从前台线程调用CurrentDispatcher并将结果传递给后台线程,或者调用DependencyObject.Dispatcher以获取窗口或其他控件的调度程序。


编辑:我只是更仔细地阅读了这个问题。 由于您不控制调用CurrentDispatcher的代码,因此它起作用的唯一方法是从 UI 线程调用该代码。

需要明确的是:我没有在我的代码中使用 Dispatcher.CurrentDispatcher。 这是在 WPF 框架代码中使用的,因此我无法更改它。 这段代码在后台线程中执行,因为我在后台线程中设置了过滤器。 我在后台线程中设置此属性,因为它可能需要几分钟。 在后台线程中设置它可以保持 UI 响应并让我向用户显示加载指示。

我通过向 Dispatcher 添加 Shutdown 并在后台线程中启动调度程序来修复内存泄漏(由未运行的后台 Dispatcher 保持对 CollectionView 的引用引起):

//All code below is executed on a background thread

//Line below causes WPF framework to add something to Dispatcher.CurrentDispatcher queue.
view.Filter = new Predicate<Object>(actionTarget.FilterCallback); 

if (Thread.CurrentThread.IsBackground &&  Dispatcher.CurrentDispatcher != Application.Current.Dispatcher)
{
    Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background);
    Dispatcher.Run();
}

如果后台线程稍后被重用(例如,因为它是一个由 BackgroundWorker 启动的线程池线程),您不能像上面的代码一样使用 BeginInvokeShutdown:无法再次启动关闭的调度程序。 在这种情况下,请使用它而不是 BeginInvokeShutdown:

Dispatcher.CurrentDispatcher.BeginInvoke((Action) delegate() { Dispatcher.ExitAllFrames(); }, DispatcherPriority.Background);

这将确保 Run() 方法返回,但稍后可以再次启动调度程序。

编辑:正如米奇在下面的评论中提到的,当多个线程可以同时执行 Run() 时要小心。 如有必要,请在 Run() 周围添加一个锁。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM