【问题标题】:Is there an alternative to use the Background Worker in WPF?有没有在 WPF 中使用后台工作人员的替代方法?
【发布时间】:2011-08-10 02:19:55
【问题描述】:

我是 WPF 的初学者,在我的应用程序中我需要执行一系列初始化步骤,这些步骤需要 10-15 秒才能完成,在此期间我的 UI 变得无响应。

我昨天使用了后台工作程序,但它没有更新我的窗口,实际上它被冻结了。不确定,但也许它不起作用,因为此控件仅适用于 Windows 窗体。

更新:

如果不是太麻烦,你能给我一个例子来使用替代方案吗?就我而言,该程序将从数据库中获取一些值。

【问题讨论】:

  • 对于后台工作者,你实现了 ReportProgress() 吗? msdn.microsoft.com/en-us/library/…
  • @Oscar:BackgroundWorker:DoWork 不会使 UI 无响应。可能您可能正在后台工作人员 AsyncCompleted 事件中进行一些 UI 更新。如果您只使用 backgroundWorkder 从数据库中检索数据,它应该可以在不冻结 UI 的情况下工作。
  • 也许我做错了什么,让我再检查一下。
  • @Oscar,即使你没有,如果后台工作人员被正确实现,表单应该能够在任务完成时移动。后台工作人员至少应该实现一个 DoWork 方法。这是一个教程,也许这会有所帮助。 switchonthecode.com/tutorials/…

标签: c# .net wpf multithreading backgroundworker


【解决方案1】:

Dispatcher。 Dispatcher 为特定线程维护工作项的优先队列。这可能会帮助您更新 UI。如果您有很多与 UI 相关的初始化,那么即使这样也无法为您提供太多帮助。

Dispatcher 实际上并不总是 BackgroundWorker 的替代品。最佳做法是根据您的要求选择更合适的一种。例如,如果您希望在不排队的情况下执行某些事情,BackgroundWorker 就是解决方案。另一方面,如果排队不是问题,那么 Dispatcher 是一个替代方案。例如,Dispatcher 正在使用拼写检查器和语法高亮功能。

WPF Thread Model

所有 WPF 应用程序都从两个重要线程开始,一个用于 渲染和一个用于管理用户界面。渲染 thread 是在后台运行的隐藏线程,所以唯一的 您通常处理的线程是 UI 线程。 WPF 要求 它的大部分对象都绑定到 UI 线程。这被称为 线程亲和性,这意味着您只能在线程上使用 WPF 对象 它是在其上创建的。在其他线程上使用它会导致 要抛出的运行时异常。注意 WPF 线程模型 与基于 Win32® 的 API 互操作性良好。这意味着 WPF 可以 托管或由任何基于 HWND 的 API(Windows 窗体、Visual Basic®、 MFC,甚至 Win32)。

线程关联由 Dispatcher 处理 类,用于 WPF 应用程序的优先消息循环。通常你的 WPF 项目有一个 Dispatcher 对象(因此只有一个 UI 线程),所有用户界面工作都通过它进行引导。

注意:

Dispatcher 与其他线程方法的主要区别 是 Dispatcher 实际上不是多线程的。调度员 管理控件,这些控件需要单个线程才能正常运行; Dispatcher 的 BeginInvoke 方法将事件排队以备后用 执行(取决于优先级等),但仍然在同一个线程上。

请参阅this 线程了解更多信息。

【讨论】:

    【解决方案2】:

    您还可以将项目与线程池一起排队并像这样运行任务,但请注意,如果您的任务需要在完成后更新 UI,您将不得不将数据编组回 UI 线程。

    【讨论】:

      【解决方案3】:

      可以使用异步委托。

      http://msdn.microsoft.com/en-us/library/ms228963.aspx

      只要确定您是否正在执行任何与 UI 相关的更新,请使用:

      Dispatcher.CheckAccess()
      

      这里是一个简单的例子:

      private void HandleUIButtons()
      {    
          if (!btnSplit.Dispatcher.CheckAccess())   
          {         
              //if here - we are on a different non-UI thread        
              btnSplit.Dispatcher.BeginInvoke(new Action(HandleUIButtons));    
          }    
          else        
          {
              btnSplit.IsEnabled = true; //this is ultimately run on the UI-thread
          }
      }
      

      取自这里:

      http://blog.clauskonrad.net/2009/03/wpf-invokerequired-dispatchercheckacces.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多