【发布时间】:2010-03-22 14:11:16
【问题描述】:
问题
我已经在这个特殊的问题上苦苦挣扎了两天,只是没有想法了。一点...背景:我们有一个 WinForms 应用程序,它需要访问数据库,从该数据构造一个相关的内存对象列表,然后显示在 DataGridView 上。重要的一点是,我们首先填充应用程序范围的缓存(List),然后创建 DGV 所在表单的本地缓存镜像(使用 List 构造函数参数)。
因为获取数据需要几秒钟的时间(数据库位于 LAN 服务器上)才能加载,我们决定使用 BackgroundWorker,并且仅在加载数据后刷新 DGV。但是,似乎通过 BGW 进行加载会导致一些内存泄漏......或者我的错误。当使用阻塞方法调用加载时,应用程序消耗大约 30MB 的 RAM;使用 BGW,这将跃升至 80MB!虽然看起来可能没有那么多,但我们的客户对此并不满意。
相关代码
表格
private void MyForm_Load(object sender, EventArgs e)
{
MyRepository.Instance.FinishedEvent += RefreshCache;
}
private void RefreshCache(object sender, EventArgs e)
{
dgvProducts.DataSource = new List<MyDataObj>(MyRepository.Products);
}
存储库
private static List<MyDataObj> Products { get; set; }
public event EventHandler ProductsLoaded;
public void GetProductsSync()
{
List<MyDataObj> p;
using (MyL2SDb db = new MyL2SDb(MyConfig.ConnectionString))
{
p = db.PRODUCTS
.Select(p => new MyDataObj {Id = p.ID, Description = p.DESCR})
.ToList();
}
Products = p;
// tell the form to refresh UI
if (ProductsLoaded != null)
ProductsLoaded(this, null);
}
public void GetProductsAsync()
{
using (BackgroundWorker myWorker = new BackgroundWorker())
{
myWorker.DoWork += delegate
{
List<MyDataObj> p;
using (MyL2SDb db = new MyL2SDb(MyConfig.ConnectionString))
{
p = db.PRODUCTS
.Select(p => new MyDataObj {Id = p.ID, Description = p.DESCR})
.ToList();
}
Products = p;
};
// tell the form to refresh UI when finished
myWorker.RunWorkerCompleted += GetProductsCompleted;
myWorker.RunWorkerAsync();
}
}
private void GetProductsCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (ProductsLoaded != null)
ProductsLoaded(this, null);
}
结束!
GetProductsSync 或 GetProductsAsync 在主线程上调用,上面没有显示。会不会是 GarbageCollector 只是因为两个线程而丢失了?还是任务管理器显示的值不对?
对任何回应、建议和批评都将不胜感激。
【问题讨论】:
-
您正在处理仍在工作的 BackgroundWorker。你不应该在那里使用
using声明。 -
是的,Slaks 是对的。在 Bgw 周围删除 using。
-
您在什么时候分离 RunWorkerComplete 事件?
-
@SkippyFire:
BackgroundWorker的Dispose方法实际上并没有做任何事情。 (只是继承自Component) -
@Henk 你在现场。不确定我是否应该评论或添加答案...在.Net Memory Profiler 下运行应用程序,然后出现一张有趣的图片 - 数字几乎相同!在同步和异步情况下,MyDataObj 实例的预期数量等于预期 (db);虚拟内存和堆大小也几乎相同。这就引出了一个问题:为什么任务管理器显示的数字大不相同?
标签: c# list datagridview backgroundworker