C#WPF应用程序使用了太多的内存,同时GC.GetTotalMemory()低 [英] C# WPF application is using too much memory while GC.GetTotalMemory() is low

查看:2605
本文介绍了C#WPF应用程序使用了太多的内存,同时GC.GetTotalMemory()低的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一点WPF应用程序有2个线程 - 主线程GUI线程而另一个线程是工人

应用与一些控制一个WPF形式。有一个按钮,允许选择目录。
在该目录中,并检查.jpg文件选择目录,应用程序扫描,如果他们的缩略图在哈希表后。如果是这样,它什么都不做。否则它的加入充分的文件名排队的工人。

工人从队列中获取文件名,加载JPEG图像(使用WPF的JpegBitmapDecoder和BitmapFrame),使它们的缩略图(使用WPF的TransformedBitmap),并把它们添加到hashtable中。

一切正常很好,除了此应用程序的内存消耗为使大图像(如5000x5000像素)缩略图时。我已经添加了我的表上的文本框,显示内存消耗(GC.GetTotalMemory()和Process.GetCurrentProcess()。PrivateMemorySize64),并感到非常惊讶的辩论,因为GC.GetTotalMemory()保持接近1-2兆,而私人内存大小不断增长,尤其是当即便加载所有图像,使它们的缩略图,并释放原始图像加载后的新形象(〜+每张图片的100Mb)。

,私有内存大小保持在〜700-800Mbytes。我的VirtualBox是限于512MB的物理内存和Windows在VirtualBox中开始换了很多来处理这个巨大的内存消耗。我想我做错事,但我不知道如何来调查这个问题的辩论,因为根据GC,分配的内存大小是非常低的。



附加代码缩略图加载类的:

 类ThumbnailLoader 
{
Hashtable的缩略图;
问答LT;字符串>任务队列;
的EventWaitHandle WH;
螺纹[]工人;
BOOL停止;
对象更衣室;
INT宽度,高度,处理,添加;

公共ThumbnailLoader()
{
INT workercount,我;
WH =新的AutoResetEvent(假);
缩略图=新的Hashtable();
=任务队列新的队列<串GT;();
停止=假;
更衣室=新的对象();
宽度=身高= 64;
加工=加入= 0;
workercount = Environment.ProcessorCount;
工人=新主题[workercount]
为(i = 0; I< workercount;我++){
工人由[i] =新主题(工人);
工人[I] .IsBackground = TRUE;
工人[I] .Priority = ThreadPriority.Highest;
工人[I]。开始();
}
}

公共无效SetThumbnailSize(INT twidth,诠释theight)
{
宽度= twidth;
高度= theight;
如果(thumbnails.Count!= 0)AddTask(#resethash);
}

公共无效GetProgress(OUT INT增加,OUT INT加工)
{
添加=增加;
=加工处理;
}

私人无效AddTask(字符串文件名)
{
锁(柜){
taskqueue.Enqueue(文件名);
wh.Set();
的加成++;
}
}

私人字符串NextTask()
{
锁(柜){
如果(taskqueue.Count == 0)返回null;
,否则{
++处理;
返回taskqueue.Dequeue();
}
}
}

公共静态字符串FileNameToHash(字符串s)
{
返回FormsAuthentication.HashPasswordForStoringInConfigFile(S,MD5 );
}

公共BOOL GetThumbnail(字符串的文件名,出BitmapFrame缩略图)
{
字符串的哈希;
哈希= FileNameToHash(文件名);
如果(thumbnails.ContainsKey(散)){
缩略图=(BitmapFrame)缩略图[散列]
返回真;
}
AddTask(文件名);
缩略图= NULL;
返回FALSE;
}

私人BitmapFrame LoadThumbnail(字符串文件名)
{
的FileStream FS;
JpegBitmapDecoder BD;
BitmapFrame oldbf,BF;
TransformedBitmap TB;
双刻度,DX,DY;
FS =新的FileStream(文件名,FileMode.Open);
BD =新JpegBitmapDecoder(FS,BitmapCreateOptions.None,BitmapCacheOption.OnLoad);
oldbf = bd.Frames [0];
DX =(双)oldbf.Width /宽度;
DY =(双)oldbf.Height /高度;
如果(DX> DY)规模= 1 / DX;
,否则规模= 1 / DY;
TB =新TransformedBitmap(oldbf,新ScaleTransform(秤,秤));
BF = BitmapFrame.Create(TB);
fs.Close();
oldbf = NULL;
BD = NULL;
GC.Collect的();
返回BF;
}

公共无效的Dispose()
{
锁(柜){
停止= TRUE;
}
AddTask(NULL);
的foreach(在岗职工螺纹工人){
worker.Join();
}
wh.Close();
}

私人无效工人()
{
串curtask,哈希;
,而(停止!){
curtask = NextTask();
如果(curtask == NULL)wh.WaitOne();
,否则{
如果(curtask ==#resethash)thumbnails.Clear();
,否则{
哈希= FileNameToHash(curtask);
尝试{
缩略图[散列] = LoadThumbnail(curtask);
}
抓{
缩略图[散列] = NULL;
}
}
}
}
}
}


解决方案

问题解决了

刚刚与BitmapCacheOption.None更换BitmapCacheOption.OnLoad:)


I wrote little WPF application with 2 threads - main thread is GUI thread and another thread is worker.
App has one WPF form with some controls. There is a button, allowing to select directory. After selecting directory, application scans for .jpg files in that directory and checks if their thumbnails are in hashtable. if they are, it does nothing. else it's adding their full filenames to queue for worker.
Worker is taking filenames from this queue, loading JPEG images (using WPF's JpegBitmapDecoder and BitmapFrame), making thumbnails of them (using WPF's TransformedBitmap) and adding them to hashtable.
Everything works fine, except memory consumption by this application when making thumbnails for big images (like 5000x5000 pixels). I've added textboxes on my form to show memory consumption (GC.GetTotalMemory() and Process.GetCurrentProcess().PrivateMemorySize64) and was very surprised, cuz GC.GetTotalMemory() stays close to 1-2 Mbytes, while private memory size constantly grows, especially when loading new image (~ +100Mb per image).
Even after loading all images, making thumbnails of them and freeing original images, private memory size stays at ~700-800Mbytes. My VirtualBox is limited to 512Mb of physical memory and Windows in VirtualBox starts to swap alot to handle this huge memory consumption. I guess I'm doing something wrong, but I don't know how to investigate this problem, cuz according to GC, allocated memory size is very low.

Attaching code of thumbnail loader class:

class ThumbnailLoader
{
    Hashtable thumbnails;
    Queue<string> taskqueue;
    EventWaitHandle wh;
    Thread[] workers;
    bool stop;
    object locker;
    int width, height, processed, added;

    public ThumbnailLoader()
    {
        int workercount,i;
        wh = new AutoResetEvent(false);
        thumbnails = new Hashtable();
        taskqueue = new Queue<string>();
        stop = false;
        locker = new object();
        width = height = 64;
        processed = added = 0;
        workercount = Environment.ProcessorCount;
        workers=new Thread[workercount];
        for (i = 0; i < workercount; i++) {
            workers[i] = new Thread(Worker);
            workers[i].IsBackground = true;
            workers[i].Priority = ThreadPriority.Highest;
            workers[i].Start();
        }
    }

    public void SetThumbnailSize(int twidth, int theight)
    {
        width = twidth;
        height = theight;
        if (thumbnails.Count!=0) AddTask("#resethash");
    }

    public void GetProgress(out int Added, out int Processed)
    {
        Added = added;
        Processed = processed;
    }

    private void AddTask(string filename)
    {
        lock(locker) {
            taskqueue.Enqueue(filename);
            wh.Set();
            added++;
        }
    }

    private string NextTask()
    {
        lock(locker) {
            if (taskqueue.Count == 0) return null;
            else {
                processed++;
                return taskqueue.Dequeue();
            }
        }
    }

    public static string FileNameToHash(string s)
    {
        return FormsAuthentication.HashPasswordForStoringInConfigFile(s, "MD5");
    }

    public bool GetThumbnail(string filename,out BitmapFrame thumbnail)
    {
        string hash;
        hash = FileNameToHash(filename);
        if (thumbnails.ContainsKey(hash)) {
            thumbnail=(BitmapFrame)thumbnails[hash];
            return true;
        }
        AddTask(filename);
        thumbnail = null;
        return false;
    }

    private BitmapFrame LoadThumbnail(string filename)
    {
        FileStream fs;
        JpegBitmapDecoder bd;
        BitmapFrame oldbf, bf;
        TransformedBitmap tb;
        double scale, dx, dy;
        fs = new FileStream(filename, FileMode.Open);
        bd = new JpegBitmapDecoder(fs, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
        oldbf = bd.Frames[0];
        dx = (double)oldbf.Width / width;
        dy = (double)oldbf.Height / height;
        if (dx > dy) scale = 1 / dx;
        else scale = 1 / dy;
        tb = new TransformedBitmap(oldbf, new ScaleTransform(scale, scale));
        bf = BitmapFrame.Create(tb);
        fs.Close();
        oldbf = null;
        bd = null;
        GC.Collect();
        return bf;
    }

    public void Dispose()
    {
        lock(locker) {
            stop = true;
        }
        AddTask(null);
        foreach (Thread worker in workers) {
            worker.Join();
        }
        wh.Close();
    }

    private void Worker()
    {
        string curtask,hash;
        while (!stop) {
            curtask = NextTask();
            if (curtask == null) wh.WaitOne();
            else {
                if (curtask == "#resethash") thumbnails.Clear();
                else {
                    hash = FileNameToHash(curtask);
                    try {
                        thumbnails[hash] = LoadThumbnail(curtask);
                    }
                    catch {
                        thumbnails[hash] = null;
                    }
                }
            }
        }
    }
}

解决方案

Solved the problem.
Just had to replace BitmapCacheOption.OnLoad with BitmapCacheOption.None :)

这篇关于C#WPF应用程序使用了太多的内存,同时GC.GetTotalMemory()低的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆