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

问题描述 投票:13回答:3

如果我在后面的代码中的函数中,并且我想在状态栏中实现显示“正在加载...”,则以下内容是有意义的,但正如我们从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中处理这个基本问题的最佳做法是什么?

c# .net wpf backgroundworker
3个回答
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();
}

2
投票

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

我遇到了以下内容,声明您可以像在Windows窗体中一样使用后台工作程序。想象一下:

BackgroundWorker现在您已经了解了Dispatcher的工作原理,您可能会惊讶地发现在大多数情况下您将无法使用它。在Windows Forms 2.0中,Microsoft引入了一个非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";
    }
}

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

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


-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);
© www.soinside.com 2019 - 2024. All rights reserved.