問題
我一直在努力解決這個問題兩天,現在只是用完了想法。有點...背景:我們有一個WinForms應用程序需要訪問數據庫,根據這些數據構造一個相關的內存對象列表,然後顯示在DataGridView上。重要的一點是,我們首先填充一個應用程序範圍的緩存(List),然後爲DGV所在的表單創建一個本地緩存的鏡像(使用List構造函數參數)。C#:BackgroundWorker克隆資源?
因爲讀取數據需要幾秒鐘的時間(DB位於局域網服務器上)加載,所以我們決定使用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 2010-03-22 14:19:49
是的,Slaks是對的。放棄在Bgw周圍使用。 – 2010-03-22 14:21:53
你在什麼時候分離RunWorkerComplete事件? – Kilhoffer 2010-03-22 14:22:19