【发布时间】:2015-04-25 08:32:22
【问题描述】:
我提前为这篇长篇道歉......
我正在寻找一些关于如何处理我在为客户编写的某些软件时遇到的问题的建议。简而言之,客户有一个第三方文件管理系统来存储他们的运输订单、发票等。当创建新文件时,客户需要保存和打印副本,以便与他们销售的商品一起发货。第三方软件制造商制作了一个带有 .NET DLL 的 SDK,它允许 C# 和 VB.NET 程序查询和保存文档。所以我给他们写了一个程序,使用这个DLL定期扫描系统,当它找到新文件时,我的程序会将它们保存到一个临时目录并打印出来。一切都很好,除了 SDK 做得不是很好,所以每当调用保存文档的方法时,一堆东西被加载到第三方 SDK 没有摆脱的 RAM 中(即它没有'不能很好地管理内存)。有时客户端会运行大批量,这种 RAM 的积累会减慢他们的系统,并导致几次内存不足异常。我写了一些示例代码来模拟这个问题。这确实需要一点想象力,但它会让你很好地了解我必须克服的问题。第一个代码示例模拟了第三方 DLL 中的一个类。
“DLL”代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Threading.Tasks;
namespace DisposeSample
{
public class OtherGuysDllClass
{
/*
This is intended to simulate the SDK class library where the memory
leak occurs. It ships with the third-party software that it integrates with, and
I can't change it. Pretend this is a .dll that I referenced in my project.
*/
public OtherGuysDllClass()
{
/*
I wrote this to simulate a process that would build up in memory over time. The SDK doesn't
do this per se, but something similar that causes junk to accumulate in RAM over time.
*/
StreamWriter sw = new StreamWriter(Environment.CurrentDirectory + "\\output.txt");
sw.WriteLine(DateTime.Now.ToString());
sw.Close();
}
}
}
可以看到,上面类中的代码中包含了一个StreamWriter对象,没有被正确的处理掉,所以会导致一些垃圾留在内存中。同样,DLL 并没有完全做到这一点,而是会导致像上面的示例那样的内存问题。
我还编写了一个带有计时器控件的 WinForms 应用程序,以定期从上述类创建一个新对象,该对象模拟我为客户端编写的程序。
我的程序:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DisposeSample
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
timer1.Interval = 500;
timer1.Enabled = true;
}
/*
Timer1 Tick Event Handler
(This Timer Control was dragged and dropped onto the form in the designer).
*/
private void timer1_Tick(object sender, EventArgs e)
{
OtherGuysDllClass dllObj = new OtherGuysDllClass();
dllObj = null;
/*
Is there any way to make the program wipe the ddlObj and everything it created from
memory? I tried calling GC.Collect(), but it didn't help much.
*/
}
}
}
因此,假设您获得了一个 DLL,其中包含一个与上面类似的类,并且您有一个全天候运行的程序,该程序会定期创建该类的实例。您将如何解决对象在内存中逐渐积累的问题。任何建议/建议将不胜感激。
谢谢!
【问题讨论】:
-
假设没有维护强引用(也就是说,我们可以“信任”OtherGuysDllClass)那么就不会有问题 - 并且.NET会正确地回收(对自己)记忆。 (“GC.Collect 没有多大帮助”这一事实表明某些对象是不可可回收的;正确实施的流将最终完成本机资源。)但是,有错误的代码,所以 iff 就是这种情况.. 创建一个新的应用程序域并让应用程序“软重启”本身? (您也可以调用另一个可重新启动的应用程序域,以不影响主应用程序。)
-
碰巧“其他人的DLL”实现了
IDisposable?也许它不是错误代码,但您的代码没有清理它应该清理的东西......? -
大声笑!好吧,我不知道我们是否可以“信任”其他人的班级,但我别无选择。他们不会很快开始使用不同的 ECM 软件,所以我想我必须这样做。
-
@KevinHerrick 我使用过商业(和“支持”)库,我必须在单独的应用程序域中运行它们并帮助他们“洗衣服”。这很烦人,但可行。 (另外,我想说的是,让长时间运行的进程有一些回收任务的方法比没有更常见 - 分配一个全新的“进程”,带有新的石板和内存池。)
-
考虑下载 ANTS 内存分析器以确认哪些对象挂在周围以及它们的根。解决内存问题的第一步是确定周围有什么。
标签: c# .net vb.net memory memory-leaks