背景工作人员从循环中进行UI更新


  • 我正在在背景工作人员的陶库内创建viewModel对象
  • 我正在报告每次迭代中的进度,将新对象作为一个参数,该参数要由ProgressChanged Handler(是UI线程的朋友)检索的参数
  • 在该处理程序中,将对象添加到带有列表的listbox的观察力汇总。

我的ViewModel类包含两个字符串属性(文件名和Thumbnailpath),其DatateMplate包含一个标签和图像,与这些属性绑定。

void bw_DoWork (object sender, DoWorkEventArgs e) {
   List<string> files = e.Argument as List<string>;
   FileInfo fi; int percent;
   for (int i = 0; i < files.Count; i++) {
      FileViewModel newItem = new FileViewModel(files[i]);
      fi = new FileInfo(files[i]);
      percent = i / files.Count * 100;
      bwImportBrowserItems.ReportProgress(percent, newItem);
   }
}
void bw_ProgressChanged (object sender, ProgressChangedEventArgs e) {
    this.observableCollection.Add(e.UserState as FileViewModel);
}

典型项目数量的典型行为(30-50):UI冻结约2-3秒;显示大约一半的物品;UI再次冻结时间较短,然后添加其余时间。

现在,我知道从循环中调用UI更新不是最好的主意 - 我认为电话频率如此频繁,UI没有时间响应它们,这就是为什么我们看到UI被"分组"更新的UI更新,在此期间使其无反应。

我尝试将 Thread.Sleep(500)作为循环的最后一行。这有助于我说明一切都应该奏效,因为随着这种放缓,项目在一个接一个地添加了一个很好的添加没有任何无反应性。

因此,我尝试了不同的睡眠值,Thread.Sleep(25)

我想问一下thread.sleep是否是这种情况下的常见解决方法,以及人们在这种情况下使用的一般解决方案是什么:从背景循环根本没有任何反应。我也想出了一些想法,我感谢您的评论。

我能想到的想法:

  1. 不要经常举报 - 将其限制为10次,或每10次新项目。
  2. 不要在循环中这样做。创建一个需要的项目列表创建。在Dowork的身体中,从列表中脱离一项,实例化并返回ViewModel实例。关于ronworkercomplet,更新UI,检查我们的列表是否为空,如果没有,
  3. 再次

如果thread.sleep在这样的情况下是常见的解决方法

认为这是最后的手段。您正在增加总处理时间(而不是CPU负载)。

1)不要经常举报 - 将其限制为10次或每10个新项目。

这是基本思想。收集新项目并通过ReportProgess派遣清单。调整列表的大小。

2)不要在循环中这样做。

可能,但是您每BGW的1个项目看起来要慢得多。它甚至可能显示出相同的症状。

3)通过同时列出的形式分解。您可以让Dowork填充队列和调度器。Timer可以将其清空。还尝试使用该计时器处理批处理。您可以调整计时器和批量大小的优先级。

最新更新