Model view controller 如何从业务/模型类发送进度更新?

Model view controller 如何从业务/模型类发送进度更新?,model-view-controller,architecture,mvvm,Model View Controller,Architecture,Mvvm,假设我们有一个具有分层体系结构的应用程序。在视图上,我们使用MVC或MVVM。该模型被视为域,它具有很好的业务逻辑部分 现在让我们假设,在模型中,有一种方法需要一些时间。一种复杂的计算或处理方法,例如,必须对一个物体的每一项进行计算或处理 在UI中,我们希望显示一个进度条和一个显示当前计算步骤的文本(例如,一个包含所有流程历史记录的列表框) 你会怎么做?如何从模型中发送流程进度信息,以及如何连接控制器或ViewModel以更新进度?您需要探索观察者模式(http://en.wikipedia.o

假设我们有一个具有分层体系结构的应用程序。在视图上,我们使用MVC或MVVM。该模型被视为域,它具有很好的业务逻辑部分

现在让我们假设,在模型中,有一种方法需要一些时间。一种复杂的计算或处理方法,例如,必须对一个物体的每一项进行计算或处理

在UI中,我们希望显示一个进度条和一个显示当前计算步骤的文本(例如,一个包含所有流程历史记录的列表框)


你会怎么做?如何从模型中发送流程进度信息,以及如何连接控制器或ViewModel以更新进度?

您需要探索观察者模式(http://en.wikipedia.org/wiki/Observer_pattern). 对于桌面应用程序来说,这是非常常见的方法。对于网络来说,这有点复杂。你们可能还想看看彗星[http://en.wikipedia.org/wiki/Comet_(编程)]以查看它是如何为Web完成的。

我通常以以下方式实现这一点。我的业务层流程需要很长时间才能运行,每隔一段时间就会引发一些事件,表明它正在达到特定的“里程碑”。您可以决定通过事件传达哪些里程碑以及其中的多少。如果您的耗时流程是一个普通循环,那么您可以选择,例如,每循环中的项目的10%,一次又一次地引发相同的事件。如果是一个具有不同阶段的流程,您可以选择在每个阶段完成时引发不同的事件

现在,您的表示层订阅这些事件,并相应地进行操作,更新进度条、文本或其他内容

这种机制很好,因为:

  • 业务层保持独立于表示层中可能发生的事情
  • 它易于扩展以实现双向通信。您可以轻松地更改事件,以便表示层(或任何其他订阅者)可以返回取消标志,以便业务层知道必须取消长时间运行的流程
  • 它允许同步或异步工作。也就是说,您可以在阻塞调用(即您的表示层和业务层共享同一线程)或非阻塞调用(即您的业务层使用后台工作线程)上使用它。在后一种情况下可以使用该类,但如果要引发多种类型的事件,则该类就不太好

  • 希望这能有所帮助。

    我对类似的案例采取了以下方法。这个观点有一个可能需要很长时间的行动,我想定期展示进展。长时间运行的操作被下推到另一个类Worker中。某些用户操作启动对TestViewModel中的
    DoSomething
    的调用

    TestView.xaml

    ...
    <!-- Progress bar -->
    <ProgressBar Visibility="Visible" Height="10" Value="{Binding SomeValue}"/>
    ...
    

    我建议查看
    System.ComponentModel
    命名空间中提供的
    BackgroundWorker

    • (winforms示例,但前提成立)
    后台工作线程提供在单独线程上运行强化操作所需的方法,并接收有关其进度的状态更新(通过
    ReportProgress
    ProgressChanged
    RunWorkerCompleted

    实际上,我个人一直在尝试在web环境中使用
    BackgroundWorker
    ,以运行计划任务。我决定在codeplex上发表我迄今为止所做的工作。我觉得我的代码的精神对你的情况很有用

    如果您选择下载项目,您将看到我如何在
    ScheduledTaskRunner
    类中使用
    BackgroundWorker
    类。我的实现没有将进度事件附加到worker,但是这样做非常容易。此外,我当前的实现侧重于在给定的时间间隔内运行任务,但将其修改为更像“按需”处理队列并不困难。现在我想起来,我甚至可以把它作为一个功能来添加:)

    假设您遵循上面我的代码的方法,那么就很容易在您的控制器上创建一个操作,该控制器将检查“任务”(或您感兴趣的特定任务)列表,并将信息报告为某种类型的
    ActionResult
    。设置一些javascript以在指定的时间间隔轮询操作,您将获得您的进度


    祝你好运,如果你对我的代码有任何疑问,请告诉我。

    基于你的其他评论,你正在努力保持你的业务层尽可能干净

    然后,模型视图模型方法可能适合:

    计算完成后,抛出已取得进展的事件

    这些事件将在ViewModel中捕获,并更新进度量


    由于ViewModel和视图(观察者模式)之间的数据绑定,视图随后被更新。

    我当然想到了观察者模式,因为它在.Net中非常常见。但我觉得这是不对的,因为这意味着在业务中有技术方面的东西,我觉得这有点错误。谢谢你的完整回答。我认为这些事件是一个非常技术性的问题,在业务层没有它的位置。但最终必须有一种方法来发送有关流程进展情况的信息。@Gimly:不客气。我认为在业务层中,事件对于实现“活动”对象很有用;你问题中的情景就是一个很好的例子。回答得很好!那么,Form.cs文件是否应该填充您自己对象的EventHandler?
    ...
    private void DoSomething(){
        Worker worker = new Worker();
        worker.ProgressChanged += new EventHandler<WorkerEventArgs>(OnProgressChanged);
        worker.Start();
    }
    
    private void OnProgressChanged(object sender, WorkerEventArgs args){
        SomeValue = args.Progress;
    }
    
    private const String SomeValuePropertyName = "SomeValue";
    private double someValue;
    public double SomeValue
    {
        get
        {
            return someValue;
        }
        set
        {
            if (someValue == value)
            {
                return;
            }
            someValue = value;
            NotifyPropertyChanged(SomeValuePropertyName);
        }
    }
    ...
    
    ...
    public event EventHandler<WorkerEventArgs> ProgressChanged;
    public void Start(){
        //This will take a long time. Periodically call NotifyProgress
    }
    
    private void NotifyProgress()
    {
        if (ProgressChanged != null)
        {
            double progress = ...; //calculate progress
            ProgressChanged(this, new WorkerEventArgs(progress));
        }
    }
    ...
    
    public class WorkerEventArgs : EventArgs
    {
        public double Progress { get; private set; }
    
        public WorkerEventArgs(double progress)
        {
            Progress = progress;
        }
    }