在WPF中,什么是Windows Forms中的Suspend / ResumeLayout()和BackgroundWorker()

时间:2008-09-17 12:57:25

标签: c# .net wpf backgroundworker

如果我在后面的代码中有一个函数,并且我想在状态栏中实现显示“正在加载...”,则以下内容是有意义的,但正如我们从WinForms中知道的那样是NoNo:

StatusBarMessageText.Text = "Loading Configuration Settings...";            
LoadSettingsGridData();
StatusBarMessageText.Text = "Done";

我们现在从WinForms第1章101类开始,在整个函数完成之前,表单不会显示对用户的更改...这意味着“加载”消息将永远不会显示给用户。需要以下代码。

Form1.SuspendLayout();    
StatusBarMessageText.Text = "Loading Configuration Settings...";                
Form1.ResumeLayout();

LoadSettingsGridData();

Form1.SuspendLayout();    
StatusBarMessageText.Text = "Done";
Form1.ResumeLayout();

在WPF中处理这个基本问题的最佳做法是什么?

3 个答案:

答案 0 :(得分:32)

最简单:

using(var d = Dispatcher.DisableProcessing())
{
    /* your work... Use dispacher.begininvoke... */
}

或者

IDisposable d;

try
{
    d = Dispatcher.DisableProcessing();
    /* your work... Use dispacher.begininvoke... */
} finally {
    d.Dispose();
}

答案 1 :(得分:2)

阅读Shawn Wildermuth撰写的文章WPF Threads: Build More Responsive Apps With The Dispatcher

我遇到了以下内容,其中指出您可以像使用WindowsForms一样使用后台工作程序。想象一下:

  

的BackgroundWorker   现在您已经了解了Dispatcher的工作原理,您可能会惊讶地发现在大多数情况下您将无法使用它。在Windows Forms 2.0中,Microsoft引入了一个非UI线程处理类,以简化用户界面开发人员的开发模型。该类称为BackgroundWorker。图7显示了BackgroundWorker类的典型用法。

     

图7在WPF中使用BackgroundWorker

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";
    }
}
     

BackgroundWorker组件适用于WPF,因为它在底层使用AsyncOperationManager类,而AsyncOperationManager类又使用SynchronizationContext类来处理同步。在Windows窗体中,AsyncOperationManager移除了从SynchronizationContext类派生的WindowsFormsSynchronizationContext类。同样,在ASP.NET中,它使用名为AspNetSynchronizationContext的SynchronizationContext的不同派生。这些SynchronizationContext派生类知道如何处理方法调用的跨线程同步。

     

在WPF中,此模型使用DispatcherSynchronizationContext类进行扩展。通过使用BackgroundWorker,Dispatcher将自动用于调用跨线程方法调用。好消息是,由于您可能已经熟悉这种常见模式,因此可以在新的WPF项目中继续使用BackgroundWorker。

答案 2 :(得分:-1)

使此工作的最简单方法是将LoadSettingsGridData添加到调度程序队列。如果将操作的DispatcherPriority设置得足够低,则会发生布局操作,您将会很高兴。

StatusBarMessageText.Text = "Loading Configuration Settings...";
this.Dispatcher.BeginInvoke(new Action(LoadSettingsGridData), DispatcherPriority.Render);
this.Dispatcher.BeginInvoke(new Action(() => StatusBarMessageText.Text = "Done"), DispatcherPriority.Render);