简体   繁体   English

WPF进度栏正常工作,但即使使用异步也被阻止在UI线程中

[英]WPF Progress bar working but blocked in UI thread even using async

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). firstLoad在加载窗口时运行,显示不确定的LW loadingWindow,并运行InitializeFilter()方法(较重的方法)。 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). 最后,当填充并加载网格时,将触发一个事件,允许关闭LW窗口并将其关闭(如果我没有使其无法关闭,那么有趣的用户可以单击或使用F4将其关闭,这不太好)。

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? 相同的LW条在MainWindow中的工作方式相似,但我缺少什么? 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. 最好的选择是使用Task.Run将繁重的处理移至线程池,并使用await检索其结果。

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. 当前的代码使用Task.Run移至线程池,然后立即转过来并使用Dispatcher移回UI线程,然后再执行繁重的处理。 Thus, it's blocking the UI thread. 因此,它阻塞了UI线程。

what this particular DataGrid displays is a CollectionView, which is not thread-safe. 此特定DataGrid显示的是CollectionView,它不是线程安全的。

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: 最好的解决方案是将繁重的处理与UI更新分开 ,如下所示:

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();
  }
}

do not use your dispatcher. 不要使用您的调度程序。 Microsoft had the foresight to use it's magic (SynchronizationContext) to be able to update the UI thread in a method that is being executed in an async context. 微软有远见,可以使用它的魔力(SynchronizationContext)来更新在异步上下文中执行的方法中的UI线程。 This is demonstrated in their async/await example found here 这在此处的异步/等待示例中得到证明

while under previous/other circumstances, you would have to either marshal back to the main (UI) thread to update the UI thread, or wait until completed and retrieve the results from objects who share state. 而在以前的/其他情况下,您将不得不编组回主(UI)线程以更新UI线程,或者等到完成并从共享状态的对象中检索结果。 Since you are using async/await then you should be fine to not use the dispatcher, and update the UI directly. 由于您正在使用async / await,因此最好不要使用调度程序,而应直接更新UI。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C#/ WPF使用异步并等待,但UI线程仍被阻止 - C#/WPF Using async and await but the UI thread is still blocked 异步下载期间C#WPF应用程序中的UI线程被阻止 - UI Thread blocked in C# WPF App during Async Download 如何在UI线程中工作时更新进度条 - How to update progress bar while working in the UI thread WPF UI线程被大集合阻止 - WPF UI Thread blocked with large collection WPF WebBrowser甚至使用ObjectForScripting在单独的线程上锁定UI - WPF WebBrowser locking UI even on separate thread using ObjectForScripting 进度栏未在WPF UI上更新 - Progress bar not getting updated on WPF UI 在ASP.NET Web应用程序中使用async / await时,UI线程被阻止 - UI thread is being blocked when using async/await with Task in ASP.NET web application UI无响应+使用BackgroundWorker C#时进度栏不起作用 - UI unresponsive + progress bar not working while using backgroundworker c# 等待Dispatcher.BeginInvoke…(使用WPF和WCF)时,我的UI线程被阻止了 - My UI thread is blocked when await Dispatcher.BeginInvoke… (using WPF and WCF) 使用WPF应用程序的UI线程对UI元素执行长时间的处理任务,还可以在同一窗口上更新进度条 - Use the UI thread of a WPF application to do a long processing task on a UI element, but also update a progress bar on the same window
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM