模型 - 视图 - 展示器模式中的缓慢操作

时间:2009-01-26 08:42:21

标签: winforms model-view-controller user-interface swt mvp

如何处理Model-View-Presenter(或MVC或M-V-VM或您使用的任何变体)中的慢速操作?

如果在WinForms或SWT / JFace或您正在使用的任何桌面框架中运行速度较慢,则必须在后台线程上运行它以避免完全锁定应用程序。你在哪里处理这个?

我可以看到几个解决方案,但我对其中任何一个都不满意:

  1. 让视图调用始终在后台线程上调用演示者。这意味着视图必须处理来自演示者的所有调用可能都来自后台线程。

  2. 让视图在主线程上调用演示者。然后,演示者在执行慢速操作时必须回调到视图中,以便可以在后台运行。

  3. 你通常做什么?

    编辑:我刚看到这篇文章:http://www.codeproject.com/KB/threads/ThreadedExecuter.aspx。它基本上是2的实现。有没有人尝试过这样的事情?

4 个答案:

答案 0 :(得分:1)

视图可以从主线程调用演示者。然后,演示者在工作线程中启动操作。并且视图(例如,使用计时器)从主线程轮询演示者,以防止回调到视图中。此致,tamberg

答案 1 :(得分:1)

我使用了一种非常类似于tamberg的方法(即使用工作线程进行处理)。

主要区别在于与视图和表示模型的交互,它具有视图直接绑定的额外状态,例如:

  • 输入停用
  • 进度更新(使用BackgroundWorker相当简单)
  • 完成通知

通过将额外状态放在表示模型而不是视图中,我可以交换视图(或者更常见的情况是,有两个视图指向同一个演示者)。

答案 2 :(得分:1)

你可以使用服务器中使用的相同的asynccallback方法到客户端框架,如GWT,只需编写一个服务器来实现你的操作,而不是在标准方法返回时返回你的结果,使用回调接口作为你的方法的参数< / p>

示例:

class ServiceX {
     void doFoo(x arg , y arg2 , callback arg3){
          //do in your thread 
          arg3.success("with return variables you need")

          // or
          arg3.failed("with exception for example");

     }

}

interface Callback {
     void success(args...);
     void failed(args ...);
}


in your view :

// do 
ServiceX bar = // get your service

bar.doFoo(a1,a2,new CallBack(){
    void succes(args ...){
    }

    void failed(args ...){
    }
});

答案 3 :(得分:1)

我用来处理这个问题。对视图方法的所有调用都被拦截并同步到UI线程。我们配置了AOP框架(spring.net)来为从IView基接口继承的所有接口执行此操作。在演示者中,我们使用属性来指示此缓慢运行的操作应在后台运行。 Presenter方法看起来像这样:

// ...
[RunInBackground]
public void TakeSomeTimeToRetrieveSomeItems
{
  var items = _svc.GetSomeItemsFromTheWeb();
  _view.ShowItems(items); // synced to UI automatically; blocks in presenter
}

在视图中,我们不需要做任何特别的事情:

// ...
public void ShowItems(IList<Item> items)
{
  itemBindingSource.DataSource = items;
}

如果您不熟悉AOP,那么使用AOP并非易事,但在这种特殊情况下,它在UI中为我们节省了大量的基础设施代码,现在我们可以轻松地开发响应式用户界面。