WPF进度条,甚至使用异步工作,但受阻于UI线程 [英] WPF Progress bar working but blocked in UI thread even using async

查看:336
本文介绍了WPF进度条,甚至使用异步工作,但受阻于UI线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实施的不确定进度条到我的程序。我是新来穿线,但据我所知,这里的最佳选择之一是增加异步方法,伺机重的功能来执行其结果。所以我写了这一点:

 公共无效Window_Loaded(对象发件人,RoutedEventArgs E)
{
    firstLoad();
}私人异步无效firstLoad()
{
    LW.Title =载入中...
    LW.Show();    filterTextBox.Text = defaultSearch;
    等待Task.Run(()=> InitializeFilter());
}私人无效InitializeFilter()
{//异步???
Dispatcher.BeginInvoke(新动作(()=> {// ... code的一些线路,需要一些时间来运行。dataGrid.ItemContainerGenerator.StatusChanged + =新的EventHandler(closeLoadingWindow);}));私人无效closeLoadingWindow(对象发件人,EventArgs的发送)
{
    如果(LW!= NULL)
    {
        LW.closable = TRUE;
        LW.Close();
    }
}

firstLoad时运行窗口被加载时,表示一个不确定LW loadingWindow以及运行InitializeFilter()方法(重一个)。最后,当电网填充并加载,事件触发,允许关闭LW窗口并关闭它(如果我没有做它不可关闭,一个有趣的用户可能只是将其关闭点击或使用F4,这是不是很好)。

该系统工作正常,一切都按预期工作有关的时间框架,但加载条被冻结,无法显示进度。同样LW栏在主窗口的工作用一组类似了我缺少什么?提前致谢!


解决方案

  

据我所知,这里的最佳选择之一是增加异步方法,伺机重的功能来执行它的结果。


最好的办法是使用 Task.Run 搬动沉重的处理线程池,并使用的await 检索其结果。

在code,因为它目前为使用 Task.Run 移动到线程池,然后立即转身并使用调度做繁重的处理前搬回到UI线程。因此,它的阻塞UI线程。


  

这是什么特别的DataGrid显示是的CollectionView,这是不是线程安全的。


右键,你不能从一个线程池线程更新数据绑定对象。

最好的解决办法是的独立的从UI更新繁重处理,这样的事情:

 公共异步无效Window_Loaded(对象发件人,RoutedEventArgs E)
{
  等待firstLoadAsync();
}私人列表<过滤式> InitializeFilter()
{
  // ... code的一些线路,需要一些时间来运行。
}私人异步任务firstLoadAsync()
{
  LW.Title =载入中...
  LW.Show();  filterTextBox.Text = defaultSearch;
  变种筛选数据=等待Task.Run(()=> InitializeFilter()); //获取在后台线程明文数据
  myCollectionView =新的CollectionView(筛选数据); //更新UI
  如果(LW!= NULL)
  {
    LW.closable = TRUE;
    LW.Close();
  }
}

I am trying to implement an indeterminate progress bar into my program. I'm new to threading, but as far as I know one of the best options here is to add an async method, and await the "heavy" function to perform its results. So I wrote this:

public void Window_Loaded(object sender, RoutedEventArgs e)
{
    firstLoad();                         
}

private async void firstLoad()
{
    LW.Title = "Loading...";
    LW.Show();

    filterTextBox.Text = defaultSearch;
    await Task.Run(() => InitializeFilter());          
}

private void InitializeFilter()
{

//Asynchronous??? 
Dispatcher.BeginInvoke(new Action(() => {

//... some lines of code that takes some time to run. 

dataGrid.ItemContainerGenerator.StatusChanged += new EventHandler(closeLoadingWindow);

}));

private void closeLoadingWindow(object sender, EventArgs e)
{
    if (LW != null)
    {
        LW.closable = true;
        LW.Close();
    }
}

firstLoad runs when the window is loaded, showing an indeterminate LW loadingWindow, and running the InitializeFilter() method (the heavy one). Finally, when the grid is populated and loaded, an event fires, allowing the LW window to be closed and closing it (if I didn't make it unclosable, a funny user could just close it clicking or using F4, which is not nice).

The system is working properly and everything works as expected regarding time frames, but the loading bar is frozen, not showing progress. The same LW bar works in the MainWindow with a similar set up What am I missing? Thanks in advance!

解决方案

as far as I know one of the best options here is to add an async method, and await the "heavy" function to perform its results

The best option is to use Task.Run to move the heavy processing to the thread pool, and use await to retrieve its results.

The code as it currently stands uses Task.Run to move to the thread pool and then immediately turns around and uses Dispatcher to move back to the UI thread before doing the heavy processing. Thus, it's blocking the UI thread.

what this particular DataGrid displays is a CollectionView, which is not thread-safe.

Right, you can't update data-bound objects from a thread pool thread.

The best solution is to separate the heavy processing from the UI updates, something like this:

public async void Window_Loaded(object sender, RoutedEventArgs e)
{
  await firstLoadAsync();
}

private List<FilterType> InitializeFilter()
{
  //... some lines of code that takes some time to run. 
}

private async Task firstLoadAsync()
{
  LW.Title = "Loading...";
  LW.Show();

  filterTextBox.Text = defaultSearch;
  var filterData = await Task.Run(() => InitializeFilter()); // Get the plain data on a background thread
  myCollectionView = new CollectionView(filterData); // Update the UI
  if (LW != null)
  {
    LW.closable = true;
    LW.Close();
  }
}

这篇关于WPF进度条,甚至使用异步工作,但受阻于UI线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆