本文介绍了使用BackgroundWorker更新界面而不会冻结...?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
从后台线程(DoWork调用PopulateThread方法),我有一个ListView的以下代码:
I have the following code for population a ListView from a background thread (DoWork calls the PopulateThread method):
delegate void PopulateThreadCallBack(DoWorkEventArgs e);
private void PopulateThread(DoWorkEventArgs e)
{
if (this.InvokeRequired)
{
PopulateThreadCallBack d = new PopulateThreadCallBack(this.PopulateThread);
this.Invoke(d, new object[] { e });
}
else
{
// Ensure there is some data
if (this.DataCollection == null)
{
return;
}
this.Hide();
// Filter the collection based on the filters
List<ServiceCallEntity> resultCollection = this.ApplyFilter();
// Get the current Ids
List<Guid> previousIdList = this.GetUniqueIdList(listView);
List<Guid> usedIdList = new List<Guid>();
foreach (ServiceCallEntity record in resultCollection)
{
if (e.Cancel)
{
this.Show();
return;
}
else
{
// Get the top level entities
UserEntity userEntity = IvdSession.Instance.Collection.GetEngineerEntity(record.UserId);
AssetEntity assetEntity = IvdSession.Instance.Collection.GetAssetEntity(record.AssetId);
SiteEntity siteEntity = IvdSession.Instance.Collection.GetSiteEntity(record.SiteId);
FaultEntity faultEntity = IvdSession.Instance.Collection.GetFaultEntity(record.FaultId);
if (siteEntity == null || userEntity == null || faultEntity == null)
{
continue;
}
else
{
// Get the linked entities
RegionEntity regionEntity = IvdSession.Instance.Collection.GetRegionEntity(siteEntity.RegionId);
StatusEntity statusEntity = IvdSession.Instance.Collection.GetStatusEntity(record.ServiceCallStatus.StatusId);
ListViewItem item = new ListViewItem(siteEntity.SiteName);
item.SubItems.Add(siteEntity.Address);
item.Tag = record;
item.SubItems.Add(regionEntity.Description);
// Handle if an Asset is involved
if (record.AssetId > 0)
item.SubItems.Add(assetEntity.AssetDisplay);
else
item.SubItems.Add("N/A");
item.SubItems.Add(faultEntity.Description);
item.SubItems.Add(userEntity.UserDisplay);
item.SubItems.Add("TODO: Claimed By");
item.SubItems.Add(record.DateTimeStamp.ToString());
IvdColourHelper.SetListViewItemColour(item, false);
this.PopulateItem(item, ref usedIdList);
}
}
}
// Clean up the grid
this.CleanListView(previousIdList, usedIdList);
// Only autosize when allowed and when there are some items in the ListView
if (this.AllowAutoSize && listView.Items.Count > 0)
{
rsListView.AutoSizeColumns(listView);
this.AllowAutoSize = false;
}
this.Show();
}
}
不幸的是导致UI冻结,而在foreach ...有没有办法更新/填充ListView没有它冻结主UI?
Unfortunately, this causes the UI to freeze whilst in the foreach... is there any way to update/populate the ListView without it freezing the main UI?
推荐答案
A)你可能不需要使用this.Invoke而是使用this.BeginInvoke。调用阻止当前线程。
A) You probably don't need to use this.Invoke and instead use this.BeginInvoke. Invoke blocks the current thread.
B)您不需要定义自己的代理您可以使用MethodInvoker
B) You don't need to define your own delegates you can use MethodInvoker
if(this.InvokeRequired) {
this.BeginInvoke(new MethodInvoker(() => PopulateThread(e)));
return;
}
更干净:)
这篇关于使用BackgroundWorker更新界面而不会冻结...?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!