如何从业务/模型类发送进度更新?
假设我们有一个具有分层架构的应用程序。在视图上我们使用 MVC 或 MVVM。模型被视为域,它有很好的业务逻辑部分。
现在假设模型中有一个需要一些时间的方法。例如,必须对对象的每个项目进行复杂的计算或处理。
在 UI 中,我们希望显示一个进度条和一个显示当前计算步骤的文本(例如包含所有过程历史记录的列表框)。
你会怎么做?如何从模型发送流程进度信息以及如何连接 Controller 或 ViewModel 以便更新进度?
Let's say we have an application that has a layered architecture. On the view we use a MVC or MVVM. The model is treated as the domain, it has a good part of the business logic.
Now let's say we have, in the model, a method that takes some time. A complicated calculation or a treatment that has to be done to each items of an object for example.
In the UI, we would like to display a progress bar and a text that would display the current step of the calculation (for example a listbox with all the process history).
How would you do that? How to send from the model the information of the progress of the process and how to hook up the Controller or ViewModel so that it will update the progress?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我经常通过以下方式实现这一点。我的业务层流程需要很长时间才能运行,经常会引发事件以表明它正在达到特定的“里程碑”。您可以决定通过事件来表明哪些里程碑以及事件的数量。例如,如果您的耗时过程是一个简单的循环,您可以选择在循环中每 10% 的项目一次又一次引发相同的事件。如果这是一个具有不同阶段的流程,您可以选择在每个阶段完成时引发不同的事件。
现在,您的表示层订阅这些事件并相应地执行操作,更新进度条、文本或其他内容。
这种机制很好,因为:
希望这有帮助。
I often implement this in the following manner. My business-layer process, which takes a long time to run, raises events every so often to indicate that it's hitting specific "milestones". You decide what milestones to signal through events and how many of them. If your time-consuming process is a plain loop, you may choose, for example, to raise the same event again and again every 10% of the items in the loop. If it is a process with distinct phases, you may choose to raise a different event as each phase is completed.
Now, your presentation layer subscribes to those events and acts in consequence, updating the progress bar, the text or whatever.
This mechanism is good because:
Hope this helps.
我建议查看
System.ComponentModel
命名空间中提供的BackgroundWorker
类。后台工作程序提供了在单独的线程上运行密集型操作所需的方法,并接收其进度的状态更新(通过 <代码>ReportProgress、
ProgressChanged
和RunWorkerCompleted
)。实际上,我个人一直在尝试在 Web 环境中使用
BackgroundWorker
来运行计划任务。我决定在 Codeplex 上发布我迄今为止所做的工作。我觉得我的代码的精神可能对您的情况有用。 “Web 计划任务框架”codeplex 项目。如果您选择下载该项目,您将看到我如何在
ScheduledTaskRunner
类中使用BackgroundWorker
类。我的实现没有将进度事件附加到工作人员,但这样做很容易。另外,我当前的实现重点是在给定的时间间隔内运行任务,但将其修改为更多的“按需”处理队列并不是很困难。现在我想到了这一点,我什至可以将其添加为一项功能:)假设您遵循上面代码的方法,那么在您的控制器上创建一个触发的操作将检查“任务”列表会很容易(或您感兴趣的特定任务)并将信息报告为某种
ActionResult
。设置一些 javascript 以在指定的时间间隔内轮询操作,您将获得进度!祝你好运,如果您对我的代码有任何疑问,请告诉我。
I would recommend looking at the
BackgroundWorker
class provided in theSystem.ComponentModel
namespace.The background worker provides the methods you need to run your intensive operation on a separate thread, and receive status updates on it's progress (via
ReportProgress
,ProgressChanged
andRunWorkerCompleted
).I actually personally have been experimenting with using the
BackgroundWorker
in a web environment, for the purpose of running scheduled tasks. I decided to publish the work I've done so far on codeplex. I feel that the spirit of my code could be useful for your situation. 'Web Scheduled Task Framework' codeplex project.If you choose to download the project, you will see how I am using the
BackgroundWorker
class in theScheduledTaskRunner
class. My implementation does not attach progress events to the worker, but it would be very easy to do so. Also, my current implementation focuses around running a task on a given interval, but modifying it to be more of an 'on demand' processing queue would not be very difficult. I may even add that as a feature now that I think about it :)Assuming you followed the approach of my code above, it would be easy to create an action on a controller of yours that went fired would inspect the list of 'tasks' (or a specific task you are interested in) and report the information as some sort of
ActionResult
. Setup some javascript to poll the action on a specified interval and you'll have your progress!Good luck and let me know if you have any questions about my code.
我对类似案例采取了以下方法。此视图的操作可能需要很长时间,我想定期显示进度。长时间运行的操作被推送到另一个类 Worker 中。某些用户操作会启动对 TestViewModel 中的
DoSomething
的调用。TestView.xaml
TestViewModel.cs 扩展了 BaseViewModel,BaseViewModel 只是实现了 INotifyPropertyChanged
Worker.cs
WorkerEventArgs.cs
I took the following approach to a similar case. This view has an action on it that can take a long time and I would like to show progress periodically. The long running action is pushed down into another class, Worker. Some user action initiates the call to
DoSomething
in TestViewModel.TestView.xaml
TestViewModel.cs extends BaseViewModel, BaseViewModel just implements INotifyPropertyChanged
Worker.cs
WorkerEventArgs.cs
根据您的其他评论,您正在努力保持业务层尽可能干净。
那么模型视图 ViewModel 方法可能适合: http://en.wikipedia.org/wiki/Model_View_ViewModel
计算完成后,您将抛出已取得进展的事件。
这些事件被捕获在 ViewModel 中,并更新进度量。
然后,由于 ViewModel 和视图之间的数据绑定(观察者模式),视图会被更新
Based on your other comments you are trying to keep your business layer as clean as possible.
Then the Model View ViewModel approach may fit: http://en.wikipedia.org/wiki/Model_View_ViewModel
As the calcualtion is done, you throw events that progress has been made.
These events are caught in the ViewModel, and the progress amount updated.
The View is then updated, due to databinding between the ViewModel and the View (Observer Pattern)
您需要探索观察者模式(http://en.wikipedia.org/wiki/Observer_pattern)。对于桌面应用程序来说,这是非常常见的方法。对于 Web 来说,情况要复杂一些。您可能还想查看 Comet [http://en.wikipedia.org/wiki/Comet_(programming)] 以了解它是如何在 Web 上实现的。
You will need to explore Observer Pattern (http://en.wikipedia.org/wiki/Observer_pattern). It's pretty common approach for desktop applications. It's a bit more complex for the Web. You might also want to look into Comet [http://en.wikipedia.org/wiki/Comet_(programming)] to see how it's done for the Web.