【问题标题】:Winforms or XmlSerializer leaks?Winforms 或 XmlSerializer 泄漏?
【发布时间】:2011-07-19 04:49:59
【问题描述】:

WinForms 应用程序,只有一个后台工作人员,只做一些事情而不做其他事情:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        try
        {
            progressBar1.Invoke(new MethodInvoker(() => { progressBar1.Value = 0; progressBar1.Maximum = Directory.GetFiles(configuration.xml.path).Count(); }));
            Directory.GetFiles(configuration.xml.path).ToList()
                .ForEach(
                p =>
                {
                    Message = XmlSerializerHelper<message>.Read(p);
                    Message.data.ToList().ForEach(www => 
                        { 
                            if (www.state == 0)www.state = 37; 
                        }
                    );
                    try
                    {
                        dataGridView1.Invoke(new MethodInvoker(() =>
                        {
                            var deb1 = Message.caption.source;
                            var deb2 = configuration.periods.Single(c => c.list_parperiod_id.ToString() == Message.caption.datatype.ToString()).name;
                            var deb3 = dataGridView1.Rows.Cast<DataGridViewRow>().Select(o => o.Cells[0].Value.ToString()).Contains(Message.caption.source);
                            var deb4 = dataGridView1.Rows.Cast<DataGridViewRow>().Select(o => o.Cells[1].Value.ToString()).Contains(
                                configuration.periods.Single(c => c.list_parperiod_id.ToString() == Message.caption.datatype.ToString()).name);
                            if (!dataGridView1.Rows.Cast<DataGridViewRow>().Select(o => new
                            {
                                source = o.Cells[0].Value.ToString(),
                                period = o.Cells[1].Value.ToString()
                            }).Contains(
                                new { 
                                    source = Message.caption.source,
                                    period = configuration.periods.Single(c => c.list_parperiod_id.ToString() == Message.caption.datatype.ToString()).name }))                   
                            {
                                textBox1.Anchor = AnchorStyles.Bottom;
                                dataGridView1.Rows.Add(Message.caption.source, configuration.periods.Single(y => y.list_parperiod_id.ToString() == Message.caption.datatype.ToString()).name, "0", "0", "0", "-");
                                if (dataGridView1.Rows.Cast<DataGridViewRow>().Count() > 7)
                                    this.Size = new System.Drawing.Size(this.Width, this.Height + 22);
                                dataGridView1.Size = new Size(dataGridView1.Width, dataGridView1.Height + 22);
                                textBox1.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom;
                            }
                        }));
                        Message.data.Where(q => q.value.Length > 0).ToList().ForEach(r =>
                            {
                                try
                                {
                                    r.value = r.value.Replace(',', '.');
                                    data.insObjParameterByCodeValueUpd(r.ucode, r.state, double.Parse(r.value, CultureInfo.InvariantCulture), DateTime.Parse(r.timestamp), null);
                                    dataGridView1.Invoke(new MethodInvoker(() =>
                                        dataGridView1.Rows.Cast<DataGridViewRow>().Single(u => 
                                            u.Cells[0].Value.ToString() == Message.caption.source.ToString() && 
                                            u.Cells[1].Value.ToString() == configuration.periods.Single(c => c.list_parperiod_id.ToString() == Message.caption.datatype.ToString())
                                            .name).Cells["lasttime"].Value = DateTime.Now.ToString()));
                                    textBox1.Invoke(new MethodInvoker(() =>
                                            {
                                                textBox1.SelectionStart = textBox1.Text.Length;
                                                textBox1.SelectionColor = Color.Black;
                                                textBox1.AppendText(System.DateTime.Now.ToString() + " загружены " + configuration.periods.Single(m=>
                                                    m.list_parperiod_id == Message.caption.datatype).name.ToLower()+ " данные за "+ Message.caption.timestamp+ " от "+ Message.caption.source + ".\r\n");
                                            })
                                        );
                                    log.Write(System.DateTime.Now.ToString() + " загружены " + configuration.periods.Single(m =>
                                                    m.list_parperiod_id == Message.caption.datatype).name.ToLower() + " данные за " + Message.caption.timestamp + " от " + Message.caption.source + ".\r\n");
                                    if ((bool)e.Argument)
                                        dataGridView1.Invoke(new MethodInvoker(() =>
                                        {
                                            dataGridView1.Rows.Cast<DataGridViewRow>().Where(u => u.Cells[0].Value.ToString() == Message.caption.source.ToString() && u.Cells[1].Value.ToString() == configuration.periods.Where(c => c.list_parperiod_id.ToString() == Message.caption.datatype.ToString()).Select(c => c.name).First().ToString()).Single().Cells["collect"].Value =
                                        (int.Parse(dataGridView1.Rows.Cast<DataGridViewRow>().Where(u => u.Cells[0].Value.ToString() == Message.caption.source.ToString() && u.Cells[1].Value.ToString() == configuration.periods.Where(c => c.list_parperiod_id.ToString() == Message.caption.datatype.ToString()).Select(c => c.name).First().ToString()).Single().Cells["collect"].Value.ToString()) + 1).ToString();
                                        }
                                          ));
                                    else
                                        dataGridView1.Invoke(new MethodInvoker(() =>
                                        {
                                            dataGridView1.Rows.Cast<DataGridViewRow>().Where(u => u.Cells[0].Value.ToString() == Message.caption.source.ToString() && u.Cells[1].Value.ToString() == configuration.periods.Where(c => c.list_parperiod_id.ToString() == Message.caption.datatype.ToString()).Select(c => c.name).First().ToString()).Single().Cells["hand"].Value =
                                        (int.Parse(dataGridView1.Rows.Cast<DataGridViewRow>().Where(u => u.Cells[0].Value.ToString() == Message.caption.source.ToString() && u.Cells[1].Value.ToString() == configuration.periods.Where(c => c.list_parperiod_id.ToString() == Message.caption.datatype.ToString()).Select(c => c.name).First().ToString()).Single().Cells["hand"].Value.ToString()) + 1).ToString();
                                        }
                                        ));

                                }
                                catch (Exception ww)
                                {
                                    if (!InfoMessage.Send(ww.Message, configuration.webservice.address, configuration.source.name))
                                        log.Write(System.DateTime.Now.ToString() + " веб сервис недоступен.\r\n");
                                    dataGridView1.Invoke(new MethodInvoker(() =>
                                            {
                                                dataGridView1.Rows.Cast<DataGridViewRow>().Where(u => u.Cells[0].Value.ToString() == Message.caption.source.ToString() && u.Cells[1].Value.ToString() == configuration.periods.Where(c => c.list_parperiod_id.ToString() == Message.caption.datatype.ToString()).Select(c => c.name).First().ToString()).Single().Cells["unknown"].Value =
                                                (int.Parse(dataGridView1.Rows.Cast<DataGridViewRow>().Where(u => u.Cells[0].Value.ToString() == Message.caption.source.ToString() && u.Cells[1].Value.ToString() == configuration.periods.Where(c => c.list_parperiod_id.ToString() == Message.caption.datatype.ToString()).Select(c => c.name).First().ToString()).Single().Cells["unknown"].Value.ToString()) + 1).ToString();
                                            })
                                        );
                                    textBox1.Invoke(new MethodInvoker(() =>
                                            {
                                                textBox1.SelectionStart = textBox1.Text.Length;
                                                textBox1.SelectionColor = Color.Red;
                                                textBox1.AppendText(System.DateTime.Now.ToString() + " " + ww.Message + "\r\n");
                                                log.Write(System.DateTime.Now.ToString() + " " + ww.Message + "\r\n");
                                            })
                                        );
                                    log.Write(System.DateTime.Now.ToString() + " " + ww.Message + "\r\n");
                                    log.Write(System.DateTime.Now.ToString() + " " + ww.Message + "\r\n");
                                }
                            });

                        if (!checkBox2.Checked)
                            File.Delete(p);
                    }
                    catch (Exception e11)
                    {
                        if (!InfoMessage.Send(e11.Message, configuration.webservice.address, configuration.source.name))
                            log.Write(System.DateTime.Now.ToString() + " веб сервис недоступен.\r\n");
                        textBox1.Invoke(
                            new MethodInvoker(() =>
                                {
                                    textBox1.SelectionStart = textBox1.Text.Length;
                                    textBox1.SelectionColor = Color.Red;
                                    textBox1.AppendText(System.DateTime.Now.ToString() + " " + e11.Message + "\r\n");
                                    log.Write(System.DateTime.Now.ToString() + " " + e11.Message + "\r\n");
                                })
                            );
                        log.Write(System.DateTime.Now.ToString() + " " + e11.Message + "\r\n");
                    }
                    progressBar1.Invoke(new MethodInvoker(() => { progressBar1.Value++; }));
                });
        }
        catch (Exception ee)
        {
            if (!InfoMessage.Send(ee.Message, configuration.webservice.address, configuration.source.name))
                log.Write(System.DateTime.Now.ToString() + " веб сервис недоступен.\r\n");
            textBox1.Invoke(new MethodInvoker(() =>
                    {
                        textBox1.SelectionStart = textBox1.Text.Length;
                        textBox1.SelectionColor = Color.Red;
                        textBox1.AppendText(System.DateTime.Now.ToString() + " " + ee.Message + "\r\n");
                    })
            );
            log.Write(System.DateTime.Now.ToString() + " " + ee.Message + "\r\n"); 
        }
    }

XmlSerializer:

public static class XmlSerializerHelper<T>
{
    public static Type _type = typeof(T);



    public static MemoryStream Save(object obj) {
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add("", "");
        XmlSerializer serializer = new XmlSerializer(_type);
        var memstr = new MemoryStream();
        serializer.Serialize(memstr, obj,ns);
        return memstr;
    }
    public static void Save(string path, object obj)
    {
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add("", "");
        using (TextWriter textWriter = new StreamWriter(path))
        {
            XmlSerializer serializer = new XmlSerializer(_type);
            serializer.Serialize(textWriter, obj, ns);
        }

    }

    public static T Read(string path)
    {
        T result;
        using (TextReader textReader = new StreamReader(path))
        {
            XmlSerializer deserializer = new XmlSerializer(_type);
            result = (T)deserializer.Deserialize(textReader);
        }
        return result;
    }
}

这些东西每 10 秒重复一次,由计时器计时。 在运行此应用程序的 2 个弱点后,该应用程序具有 150Mb 的内存。 这里会泄漏什么?

【问题讨论】:

  • 在 1 天、2 天、1 周、2 周、4 周后使用了多少内存?它是增加还是被回收?
  • 它在增加。从30-40Mb开始,然后线性增加
  • 在多长时间内?我预计它最初会增加,但它是否(显着)超过 150Mb?请注意,使用同一台机器执行所有测试很重要。我同意 Marc 在下面的回答,但这将有助于让您放心,没有泄漏。
  • @Jack 你还没有回答我的你如何衡量这个问题 - 这很重要。

标签: .net winforms memory-leaks


【解决方案1】:

在运行此应用程序的 2 个弱点后,有 150Mb 的内存。

什么都没有;这很好。内存可以使用,应用程序不必过于害羞地使用它。听起来不像是在出血;随它去。

【讨论】:

  • (@JackBrown 对已删除的意外副本的评论):不。如果它从 20Mb 开始,为什么内存会增加?有一天它会内存不足。不想
  • @JackBrown 是否曾因内存不足而失败?系统响应诸如内存压力之类的事情;即 需求 内存。如果没有什么东西在争夺内存……还有:你是如何衡量这个的?因为大多数数字(包括任务管理器中的数字)都是谎言
【解决方案2】:

XmlSerializer suffers a memory leak

我不知道它是否仍然发生在 .NET 4.0 中,但它仍然存在于 .NET 3.5 中。

因为您正在运行一个 winforms 应用程序,所以还不错,因为在应用程序关闭时会释放资源 - 如果它关闭...

我通过编写一个使用大量 XML 序列化和其他非托管资源的 Windows 服务来体验这种情况。非托管代码由于内存中断而崩溃,我很难找到它的来源。

mvpxml libraryXmlSerializerCache 拯救了我的生命。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    • 1970-01-01
    • 2014-05-01
    • 2013-06-26
    相关资源
    最近更新 更多