如何处理Model-View-Presenter(或MVC或M-V-VM或您使用的任何变体)中的慢速操作?
如果在WinForms或SWT / JFace或您正在使用的任何桌面框架中运行速度较慢,则必须在后台线程上运行它以避免完全锁定应用程序。你在哪里处理这个?
我可以看到几个解决方案,但我对其中任何一个都不满意:
让视图调用始终在后台线程上调用演示者。这意味着视图必须处理来自演示者的所有调用可能都来自后台线程。
让视图在主线程上调用演示者。然后,演示者在执行慢速操作时必须回调到视图中,以便可以在后台运行。
你通常做什么?
编辑:我刚看到这篇文章:http://www.codeproject.com/KB/threads/ThreadedExecuter.aspx。它基本上是2的实现。有没有人尝试过这样的事情?
答案 0 :(得分:1)
视图可以从主线程调用演示者。然后,演示者在工作线程中启动操作。并且视图(例如,使用计时器)从主线程轮询演示者,以防止回调到视图中。此致,tamberg
答案 1 :(得分:1)
我使用了一种非常类似于tamberg的方法(即使用工作线程进行处理)。
主要区别在于与视图和表示模型的交互,它具有视图直接绑定的额外状态,例如:
通过将额外状态放在表示模型而不是视图中,我可以交换视图(或者更常见的情况是,有两个视图指向同一个演示者)。
答案 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)
我用aop来处理这个问题。对视图方法的所有调用都被拦截并同步到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中为我们节省了大量的基础设施代码,现在我们可以轻松地开发响应式用户界面。