If I am in a function in the code behind, and I want to implement displaying a "Loading..." in the status bar the following makes sense, but as we know from WinForms is a NoNo:
如果我在代码后面的一个函数中,并且我想在状态栏中显示一个“load…”,以下是有意义的,但是正如我们从WinForms中知道的,它是一个NoNo:
StatusBarMessageText.Text = "Loading Configuration Settings...";
LoadSettingsGridData();
StatusBarMessageText.Text = "Done";
What we all now from WinForms Chapter 1 class 101, is the form won't display changes to the user until after the Entire Function completes... meaning the "Loading" message will never be displayed to the user. The following code is needed.
从WinForms (WinForms)第一章第101类开始,我们都知道表单在整个功能完成后才会显示对用户的更改……意味着“装载”消息将永远不会显示给用户。需要以下代码。
Form1.SuspendLayout();
StatusBarMessageText.Text = "Loading Configuration Settings...";
Form1.ResumeLayout();
LoadSettingsGridData();
Form1.SuspendLayout();
StatusBarMessageText.Text = "Done";
Form1.ResumeLayout();
What is the best practice for dealing with this fundamental issue in WPF?
在WPF中,处理这个基本问题的最佳实践是什么?
3 个解决方案
#1
31
Best and simplest:
最好的和最简单的:
using(var d = Dispatcher.DisableProcessing())
{
/* your work... Use dispacher.begininvoke... */
}
Or
或
IDisposable d;
Try
{
d = Dispatcher.DisableProcessing();
/* your work... Use dispacher.begininvoke... */
} Finally {
d.Dispose();
}
#2
2
In reading the article by Shawn Wildermuth WPF Threads: Build More Responsive Apps With The Dispatcher.
在阅读Shawn Wildermuth WPF Threads的文章时:使用Dispatcher构建响应更快的应用程序。
I came accross the following, which states you can use the Background Worker just like you could in WindowsForms. Fancy that:
我接着说,你可以像使用windows窗体一样使用后台工作程序。真想不到:
BackgroundWorker Now that you have a sense of how the Dispatcher works, you might be surprised to know that you will not find use for it in most cases. In Windows Forms 2.0, Microsoft introduced a class for non-UI thread handling to simplify the development model for user interface developers. This class is called the BackgroundWorker. Figure 7 shows typical usage of the BackgroundWorker class.
既然您已经了解了分派器的工作方式,那么您可能会惊讶地发现,在大多数情况下您不会发现它的用处。在Windows Forms 2.0中,微软引入了一个用于非ui线程处理的类,以简化用户界面开发人员的开发模型。这个类叫做BackgroundWorker。图7显示了BackgroundWorker类的典型用法。
Figure 7 Using a BackgroundWorker in WPF
BackgroundWorker _backgroundWorker = new BackgroundWorker(); ... // Set up the Background Worker Events _backgroundWorker.DoWork += _backgroundWorker_DoWork; backgroundWorker.RunWorkerCompleted += _backgroundWorker_RunWorkerCompleted; // Run the Background Worker _backgroundWorker.RunWorkerAsync(5000); ... // Worker Method void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { // Do something } // Completed Method void _backgroundWorker_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled) { statusText.Text = "Cancelled"; } else if (e.Error != null) { statusText.Text = "Exception Thrown"; } else { statusText.Text = "Completed"; } }
The BackgroundWorker component works well with WPF because underneath the covers it uses the AsyncOperationManager class, which in turn uses the SynchronizationContext class to deal with synchronization. In Windows Forms, the AsyncOperationManager hands off a WindowsFormsSynchronizationContext class that derives from the SynchronizationContext class. Likewise, in ASP.NET it works with a different derivation of SynchronizationContext called AspNetSynchronizationContext. These SynchronizationContext-derived classes know how to handle the cross-thread synchronization of method invocation.
BackgroundWorker组件在WPF上工作得很好,因为它在底层使用AsyncOperationManager类,而AsyncOperationManager类又使用SynchronizationContext类来处理同步。在Windows窗体中,AsyncOperationManager从同步上下文类派生出一个WindowsFormsSynchronizationContext类。同样,在ASP。NET与同步上下文的另一种派生方法AspNetSynchronizationContext,称为AspNetSynchronizationContext。这些同步上下文派生的类知道如何处理方法调用的跨线程同步。
In WPF, this model is extended with a DispatcherSynchronizationContext class. By using BackgroundWorker, the Dispatcher is being employed automatically to invoke cross-thread method calls. The good news is that since you are probably already familiar with this common pattern, you can continue using BackgroundWorker in your new WPF projects.
在WPF中,该模型与DispatcherSynchronizationContext类一起扩展。通过使用BackgroundWorker,将自动使用Dispatcher来调用跨线程方法调用。好消息是,由于您可能已经熟悉了这个通用模式,所以您可以在新的WPF项目中继续使用BackgroundWorker。
#3
-1
The easiest way to get this to work is to add the LoadSettingsGridData to the dispatcher queue. If you set the operation's DispatcherPriority sufficiently low enough, the layout operations will occur, and you will be good to go.
使其工作的最简单方法是将LoadSettingsGridData添加到dispatcher队列。如果您将操作的DispatcherPriority设置得足够低,那么布局操作就会发生,您将会很好地运行。
StatusBarMessageText.Text = "Loading Configuration Settings...";
this.Dispatcher.BeginInvoke(new Action(LoadSettingsGridData), DispatcherPriority.Render);
this.Dispatcher.BeginInvoke(new Action(() => StatusBarMessageText.Text = "Done"), DispatcherPriority.Render);
#1
31
Best and simplest:
最好的和最简单的:
using(var d = Dispatcher.DisableProcessing())
{
/* your work... Use dispacher.begininvoke... */
}
Or
或
IDisposable d;
Try
{
d = Dispatcher.DisableProcessing();
/* your work... Use dispacher.begininvoke... */
} Finally {
d.Dispose();
}
#2
2
In reading the article by Shawn Wildermuth WPF Threads: Build More Responsive Apps With The Dispatcher.
在阅读Shawn Wildermuth WPF Threads的文章时:使用Dispatcher构建响应更快的应用程序。
I came accross the following, which states you can use the Background Worker just like you could in WindowsForms. Fancy that:
我接着说,你可以像使用windows窗体一样使用后台工作程序。真想不到:
BackgroundWorker Now that you have a sense of how the Dispatcher works, you might be surprised to know that you will not find use for it in most cases. In Windows Forms 2.0, Microsoft introduced a class for non-UI thread handling to simplify the development model for user interface developers. This class is called the BackgroundWorker. Figure 7 shows typical usage of the BackgroundWorker class.
既然您已经了解了分派器的工作方式,那么您可能会惊讶地发现,在大多数情况下您不会发现它的用处。在Windows Forms 2.0中,微软引入了一个用于非ui线程处理的类,以简化用户界面开发人员的开发模型。这个类叫做BackgroundWorker。图7显示了BackgroundWorker类的典型用法。
Figure 7 Using a BackgroundWorker in WPF
BackgroundWorker _backgroundWorker = new BackgroundWorker(); ... // Set up the Background Worker Events _backgroundWorker.DoWork += _backgroundWorker_DoWork; backgroundWorker.RunWorkerCompleted += _backgroundWorker_RunWorkerCompleted; // Run the Background Worker _backgroundWorker.RunWorkerAsync(5000); ... // Worker Method void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { // Do something } // Completed Method void _backgroundWorker_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled) { statusText.Text = "Cancelled"; } else if (e.Error != null) { statusText.Text = "Exception Thrown"; } else { statusText.Text = "Completed"; } }
The BackgroundWorker component works well with WPF because underneath the covers it uses the AsyncOperationManager class, which in turn uses the SynchronizationContext class to deal with synchronization. In Windows Forms, the AsyncOperationManager hands off a WindowsFormsSynchronizationContext class that derives from the SynchronizationContext class. Likewise, in ASP.NET it works with a different derivation of SynchronizationContext called AspNetSynchronizationContext. These SynchronizationContext-derived classes know how to handle the cross-thread synchronization of method invocation.
BackgroundWorker组件在WPF上工作得很好,因为它在底层使用AsyncOperationManager类,而AsyncOperationManager类又使用SynchronizationContext类来处理同步。在Windows窗体中,AsyncOperationManager从同步上下文类派生出一个WindowsFormsSynchronizationContext类。同样,在ASP。NET与同步上下文的另一种派生方法AspNetSynchronizationContext,称为AspNetSynchronizationContext。这些同步上下文派生的类知道如何处理方法调用的跨线程同步。
In WPF, this model is extended with a DispatcherSynchronizationContext class. By using BackgroundWorker, the Dispatcher is being employed automatically to invoke cross-thread method calls. The good news is that since you are probably already familiar with this common pattern, you can continue using BackgroundWorker in your new WPF projects.
在WPF中,该模型与DispatcherSynchronizationContext类一起扩展。通过使用BackgroundWorker,将自动使用Dispatcher来调用跨线程方法调用。好消息是,由于您可能已经熟悉了这个通用模式,所以您可以在新的WPF项目中继续使用BackgroundWorker。
#3
-1
The easiest way to get this to work is to add the LoadSettingsGridData to the dispatcher queue. If you set the operation's DispatcherPriority sufficiently low enough, the layout operations will occur, and you will be good to go.
使其工作的最简单方法是将LoadSettingsGridData添加到dispatcher队列。如果您将操作的DispatcherPriority设置得足够低,那么布局操作就会发生,您将会很好地运行。
StatusBarMessageText.Text = "Loading Configuration Settings...";
this.Dispatcher.BeginInvoke(new Action(LoadSettingsGridData), DispatcherPriority.Render);
this.Dispatcher.BeginInvoke(new Action(() => StatusBarMessageText.Text = "Done"), DispatcherPriority.Render);