V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
soooulp
V2EX  ›  问与答

Winform 关闭窗口后如何清理内存?

  •  
  •   soooulp · 2022-03-22 15:15:48 +08:00 · 975 次点击
    这是一个创建于 982 天前的主题,其中的信息可能已经有所发展或是发生改变。

    打开 Winform 窗口后,内存一直增加,关闭窗口后,内存不会还原,使用Dispose();没有效果

    比如第一段代码中使用 Winform 显示图片

    另外找到 .NET API 中,GC.Collect();SetProcessWorkingSetSize函数,会降低内存显示,实际上是转移到虚拟内存中,效果非常不好

    是否有好的办法关闭 form 窗口后,清理内存的呢

    var Forms = forms.System.Windows.Forms;
    var form = new Forms.Form;
    form.StartPosition = Forms.FormStartPosition.Manual;
    form.FormBorderStyle = Forms.FormBorderStyle.None;
    form.TopMost = true;
    form.ControlBox = false;
    form.ShowInTaskbar = false;
    form.Margin = new Forms.Padding(0);
    form.Padding = new Forms.Padding(1);
    form.MinimumSize = new Size(10, 10);
    form.Size = new Size(10, 10);
    form.Location = new Point(100, 100);
    form.AutoSize = true;
    form.GetType().GetProperty("DoubleBuffered",
        host.flags(clr.System.Reflection.BindingFlags.NonPublic,
        clr.System.Reflection.BindingFlags.Instance))
        .SetValue(form, true);
    form.BackColor = drawing.System.Drawing.SystemColors.HotTrack;
    
    var pic = new Forms.PictureBox;
    pic.Name = 'pic';
    pic.SizeMode = Forms.PictureBoxSizeMode.Zoom;
    pic.Size = new Size(450, 500);
    pic.BackColor = drawing.System.Drawing.SystemColors.Control;
    pic.Location = new Point(0, 0);
    pic.Image = img;
    
    form.Controls.Add(pic);
    var autoSize = form.Size;
    var t = (form.ClientSize.Width - pic.Width - form.Padding.Horizontal);
    autoSize.Width -= t;
    autoSize.Height -= t;
    form.AutoSize = false;
    form.Size = autoSize;
    pic.Dock = Forms.DockStyle.Fill;
    
    var form_shown = 
    form.Shown.connect(
    function (sender, args) {
        form.TopMost = true;
        form.Activate();
    });
    
    var pic_doubleClick = 
    pic.DoubleClick.connect(
    function (sender, args) {
        form.Dispose();
        pic.Dispose();
        Forms.Application.Exit();
        form.Close(); 
    });
    
    Forms.Application.Run(form);
    img.Dispose();
    

    使用SetProcessWorkingSetSize

    form.Close(); 
    FlushMemory();
    function FlushMemory()
    {
        System.GC.Collect();
        System.GC.WaitForPendingFinalizers();
        if (System.Environment.OSVersion.Platform == System.PlatformID.Win32NT)
            SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
    } 
    
    5 条回复    2022-03-22 21:07:45 +08:00
    zhaofish
        1
    zhaofish  
       2022-03-22 15:26:55 +08:00
    你是怎么看内存占用的? double click 之后 Application.Exit ,程序就退出了,怎么还有内存占用
    soooulp
        2
    soooulp  
    OP
       2022-03-22 15:36:46 +08:00
    软件里面新建的 Form ,关闭了通过 form 显示的图片窗口,程序还未关哦
    zhaofish
        3
    zhaofish  
       2022-03-22 16:48:18 +08:00
    @soooulp 确认 img 对象是否被正确释放了。你这个写法也不是 C#推荐的写法,如果是继承了 IDisposable 接口的对象,应该使用 using 语句包裹。Forms.Application.Run(form)是不是阻塞式的,要等 form.Close 调用后才转到 img.Dispose ,而你在 doubleclick 里面是不是抛异常了,导致 img.Dispose 没有被调用。

    是不是我落伍了,C#里面有 function(s, args)这种语句?不应该是 pic.DoubleClick += (sender, args) => ...这种写法吗?
    soooulp
        4
    soooulp  
    OP
       2022-03-22 17:15:04 +08:00
    @zhaofish 嗯嗯,封装过啦,没有异常,估计是 img.Dispose 没执行,换成 form.ShowDialog();貌似内存也没变化
    ysc3839
        5
    ysc3839  
       2022-03-22 21:07:45 +08:00 via Android
    GC.Collect 是真的回收内存,而不是转移到虚拟内存吧?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4666 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 04:02 · PVG 12:02 · LAX 20:02 · JFK 23:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.