首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c# Image.FromFile -批量操作?

c# Image.FromFile -批量操作?
EN

Stack Overflow用户
提问于 2018-10-09 01:35:30
回答 1查看 129关注 0票数 0

为了保持性能“高”,当使用我们的应用程序时,我们对所有的列表视图使用(预加载的)图像列表。

biggeset listview可以包含大约9000张图像的imagelist。

因此,为了生成图像列表,我们使用了addRange(),它可以在几乎没有时间的情况下完成这项工作。

但是,在启动期间,将映像从文件系统“加载”到image[]数组仍然需要4-5秒。(约80 MB,在固态硬盘上)

我想知道是否有更好的方法从(本地)文件系统中填充“大”图像列表?

目前我们使用的是:

代码语言:javascript
复制
System.IO.DirectoryInfo di2 = new System.IO.DirectoryInfo(Config.ProductImageLocalPath);
System.IO.FileInfo[] files2 = di.EnumerateFiles("*.jpg", SearchOption.AllDirectories).ToArray();

int idx = 1; //0 is reservevd for default image, which is already added.
foreach (FileInfo fi in files2)
{
    Resources.ImageIndex.Add(long.Parse(Path.GetFileNameWithoutExtension(fi.Name)), idx++);
}

Image[] images = Array.ConvertAll(files2, file => Image.FromFile(file.FullName));

Resources.ProductImageList_256.Images.AddRange(images);

ImageIndex只是一个dictionary<Long, int>,它允许将实际的id (从文件名派生)映射到相应图像映射中的从0开始的索引,并且不需要任何时间来生成。

显然,Image[] images = Array.ConvertAll(files2, file => Image.FromFile(file.FullName));是瓶颈,因为这相当于对Image.fromFile的9000次调用(是否也有一些批量选项?)。

这里有什么“更好”的点子吗?

EN

回答 1

Stack Overflow用户

发布于 2018-10-09 02:51:55

好吧,所以我写了一个函数,它将完成分配给几个线程的工作-然后在我的代码中发现了一个"bug“。(然而,使用多线程也有很大帮助,所以image.fromFile的瓶颈显然是中央处理器,而不是(本地)固态硬盘)。

1。)网络加载

在上面提到的代码中:System.IO.FileInfo[] files2 = di.EnumerateFiles("*.jpg", SearchOption.AllDirectories).ToArray(); -I使用di而不是di2进行枚举(di指的是网络共享)

(所以Array.ConvertAll正在访问远程文件)

“此”方法的运行时:6s 414ms

2。)本地加载

修复导致1s 886ms运行时出现的问题

3。)本地线程加载

但是,我的ThreadedLoading-Function已经完成了,所以我也尝试了一下:

0s 543ms -所以在有4个物理核心的8核上仍然要快4倍。

这是代码。可能还不是防弹的,但会产生可靠且快速的(估计)结果。

用法:

代码语言:javascript
复制
 DateTime t1 = DateTime.Now;
//Image[] images = Array.ConvertAll(files2, file => Image.FromFile(file.FullName));
Image[] images = loadImagesThreaded(files2);
DateTime t2 = DateTime.Now;

TimeSpan ts = t2.Subtract(t1);
MessageBox.Show("Loading took: " + ts.Seconds + "s " + ts.Milliseconds + "ms"); //6s 414ms

Resources.ProductImageList_256.Images.AddRange(images);

功能:

代码语言:javascript
复制
private Image[] loadImagesThreaded(FileInfo[] files)
{
    int threadCount = 8;
    int chunkSize = files.Length / threadCount; //Round about -  doesn't need to be precise. 
    Thread[] threads = new Thread[threadCount];
    Image[][] result = new Image[threadCount][];

    for (int i = 0; i < threadCount; i++)
    {
        FileInfo[] chunk;
        int lowerBound = i * chunkSize;
        if (i < threadCount - 1)
        {
            chunk = files.Skip(lowerBound).Take(chunkSize).ToArray();
        }
        else
        {
            //take the rest
            chunk = files.Skip(lowerBound).ToArray();
        }

        int j = i; 
        threads[i] = new Thread(() =>
        {
            result[j] = Array.ConvertAll(chunk, file => Image.FromFile(file.FullName));
        });
        threads[i].Start();
    }

    //wait for threads to finish. 
    Boolean oneAlive = true;
    while (oneAlive)
    {
        oneAlive = false;
        foreach (Thread t in threads)
        {
            if (t.IsAlive)
            {
                oneAlive = true;
                break;
            }
        }
    }

    //all done. 
    Image[] finalResult = new Image[files.Count()];
    for (int i = 0; i < threadCount; i++)
    {
        int lowerBound = i * chunkSize;
        result[i].CopyTo(finalResult, lowerBound);
    }
    return finalResult;
}

这不是一个很好的峰值吗,同时预加载图像?:-)

4。)Parallel.ForEach

根据Felipe Ramos的推荐,我尝试了Parallel.ForEach。它比我的“线程化”解决方案快了大约40-50毫秒(主要是480-500毫秒)--但也许更重要的事实是:

这是不需要动脑筋的,因此更可靠,我要说:

代码语言:javascript
复制
Image[] images = new Image[files2.Count()];
Parallel.ForEach(files2, (fileInfo, state, index) =>
{
    images[index] = Image.FromFile(fileInfo.FullName);
});

DateTime t2 = DateTime.Now;
TimeSpan ts = t2.Subtract(t1);
MessageBox.Show("Loading took: " + ts.Seconds + "s " + ts.Milliseconds + "ms");
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52707427

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档