Проблема
Я боролся с этой частичной проблемой уже два дня и просто иссякли идеи.Немного ... предыстория: у нас есть приложение WinForms, которое должно получить доступ к базе данных, создать список связанных объектов в памяти из этих данных и затем отобразить в DataGridView.Важным моментом является то, что мы сначала заполняем кэш приложения (List), а затем создаем зеркало кеша, локальное для формы, в которой живет DGV (используя параметр конструктора List).
Поскольку происходит выборка данныхзагрузка занимает несколько секунд (БД находится на сервере ЛВС), мы решили использовать BackgroundWorker и обновлять DGV только после загрузки данных.Однако, похоже, что загрузка через BGW приводит к некоторой утечке памяти ... или ошибке с моей стороны.При загрузке с использованием вызова метода блокировки приложение потребляет около 30 МБ ОЗУ;с BGW это прыгает до 80 МБ!Хотя в любом случае это может показаться не таким уж большим, наши клиенты не слишком рады этому.
Соответствующий код
Форма
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 просто теряется с двумя потоками?Или это диспетчер задач, который показывает неправильные значения?
Буду благодарен за любые ответы, предложения, критику.