Incrementalloading Collection会加载所有数据,并且不会释放内存

如何解决Incrementalloading Collection会加载所有数据,并且不会释放内存

我的ListView仅包含在其上呈现了pdf页面的图像控件。我正在通过一种方法获取每个页面,该方法通过一个简单的循环调用,只要剩下页面就可以了。由于pdf可能真的很大,由于渲染的页面数量,我有时会遇到内存不足的异常。我阅读了有关Ui和数据虚拟化的文章,而UI虚拟化似乎可以正常工作,而我的数据虚拟化却没有。 我阅读了Incrementalloading集合并实现了该接口。在这个集合中,我添加了我从方法中获得的每张图像。我看到GetPagedItemsAsync方法在程序开始时仅被调用一次。

public class IncrementalLoadingCollection :  IIncrementalSource<Image>
{      
    Rendering u;
    public IncrementalLoadingCollection()
    {
      
    }
    public async Task<IEnumerable<Image>> GetPagedItemsAsync(int pageIndex,int pageSize,CancellationToken cancellationToken = default)
    {
        u = new Rendering();          
        var result = (from p in u.collection select p).Skip(pageIndex * pageSize).Take(pageSize);

        await Task.Delay(1000);
        
        return result;
    }       
}

渲染是我的课程,负责执行文档和单页的加载。 我将在下面提供一个代码片段,我想问一下:接口的实现是否错误或者是否有更严重的错误使数据无法增量加载?

在Rendering.cs中:

在构造函数中:

     public IncrementalLoadingCollection<IncrementalLoadingCollection,Image> collection = new IncrementalLoadingCollection<IncrementalLoadingCollection,Image>();

在loadDocument函数中:

for (uint i = 0; i <= l_document.PageCount - 1; i++)

{

                    Image img = await LoadPage(l_document,i);                   
                    collection.Add(img);
                    g_rootPage.ListViewControl.ItemsSource = collection;
                    

}

EDIT1:

我在Github上放了一个程序的小例子,其中包含了除异常处理之类的基本功能。

https://github.com/ShionLightwood/PDFDemo

解决方法

我检查了您的项目,IIncrementalSource接口的实现可能存在一些问题。

PdfDocument可以根据页面索引加载页面。因此,增量加载意味着我们需要在页面滚动到底部时从PdfDocument的当前页面索引之后获取页面,而不是在开始时加载所有页面,然后使用Task.Delay强制延迟。

因此,我的建议是创建一个PdfSource类,其目的与原始IncrementalLoadingCollection(在项目中)相同,用于处理增量加载。但是不同之处在于,内置变量是PdfDocument的实例。

public class PdfSource : IIncrementalSource<BitmapImage>
{
    private PdfDocument _document;

    public PdfSource(PdfDocument doc)
    {
        _document = doc;
    }

    public async Task<IEnumerable<BitmapImage>> GetPagedItemsAsync(int pageIndex,int pageSize,CancellationToken cancellationToken = default)
    {
        List<BitmapImage> result = new List<BitmapImage>();
        int count = 0;
        if (pageIndex < _document.PageCount)
        {
            for (int i = pageIndex; i < _document.PageCount; i++)
            {
                count++;
                if (count == pageSize)
                    break;
                var bitmap = await GetPageAsync((uint)i);
                if (bitmap != null)
                    result.Add(bitmap);
            }
        }
        return result;
    }

    private async Task<BitmapImage> GetPageAsync(uint index)
    {
        var bitmap = new BitmapImage();
        PdfPage pdfPage;
        PdfPageRenderOptions option = new PdfPageRenderOptions();
        option.DestinationHeight = 1200;
        option.DestinationWidth = 1000;
        using (IRandomAccessStream Imagestream = new MemoryStream().AsRandomAccessStream())
        {
            try
            {
                using (pdfPage = _document.GetPage(index))
                {
                    await pdfPage.RenderToStreamAsync(Imagestream,option);
                    await bitmap.SetSourceAsync(Imagestream);
                    bitmap.DecodePixelHeight = 1200;
                    bitmap.DecodePixelWidth = 1000;
                }
                return bitmap;
            }
            catch (ArgumentException ex)
            {
                Windows.UI.Popups.MessageDialog accessDenial = new Windows.UI.Popups.MessageDialog(ex.Message);
                await accessDenial.ShowAsync();
            }
        }
        return default;
    }
}

有两点需要解释:

  1. 使用BitmapImage替换Image,因为Image是一个控件,我们可以在ListView.ItemTemplate中创建它
  2. option.DestinationHeight修改为合适的值,太大会影响加载速度。

在“渲染”类中,我们还需要进行修改。

class Rendering
{
    private MainPage g_rootPage;       
    PdfDocument l_document;
    public IncrementalLoadingCollection<PdfSource,BitmapImage> collection;

    public Rendering()
    {
        g_rootPage = MainPage.Current;
    }

    public async Task LoadDocument(string source)
    {
        StorageFile l_file;
        l_file = await StorageFile.GetFileFromPathAsync(source);
        l_document = await PdfDocument.LoadFromFileAsync(l_file);
        var pdfSource = new PdfSource(l_document);
        collection = new IncrementalLoadingCollection<PdfSource,BitmapImage>(pdfSource);
        g_rootPage.ListViewControl.ItemsSource = collection;
    }
}

MainPage.xaml

<ListView ...>
    <!-- other code -->
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="BitmapImage">
            <Image Source="{Binding}"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

修改完成后,增量加载即可正常运行。也就是说,滚动到底部进行加载(您可以添加一些加载说明UI)。加载完成后,内存使用量将大大下降。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-