UI和应用程序的关系
我读过很多关于 UI、业务逻辑、WCF、IoC 的文章,但我仍然缺少一件事。 我构建了一个 winforms 应用程序和一个控制台应用程序。控制台应用程序是大脑。 现在,在所有客户端-服务器架构中,客户端“知道”服务器,向他发送请求并获得答案。我的问题如下:
1)如果用户不知道用户界面的存在,控制台应用程序如何向用户显示消息? UI 是否应该每 x 毫秒检查并池化消息?这是一个好方法吗?
2)如果UI表单应该显示股票价格,例如一直变化的股票价格,该怎么办?它是否应该每 200 毫秒向控制台应用程序请求一次股票价格?或者在控制台应用程序中注册回调函数以便控制台应用程序可以调用它?但是,现在不是把UI变成了服务器吗?
3)如果我想向我的应用程序添加终端功能(例如telnet cli)会发生什么,我应该如何设计它? telnet 服务器作为客户端,我的控制台应用程序作为服务器?有没有一种设计可以帮助我实现这一目标?出租车?我问了很多人,好像没有人用……是这样吗?
谢谢, 埃亚勒
I've read a lot of articles about the UI ,buisness logic ,WCF ,IoC, but still, one thing is missing from my mind.
I build a winforms application and a console app. the Console App is the brain.
Now, in all the client-server architecture the client "know" the server , send him request and get the answer. My qestion is as follow:
1) How can the console application display a message to the user if he doens't know the existence of the UI? Should the UI check and pool for the messages every x msec? is it a good approach?
2) what in the case that the UI forms should display a ticker price ,e.g stock price which changes all the time ? should it request the ticker price from the console app every 200msec? or register a callback function in the console application so the console application can call it? However, doesn't it make the UI into a server now?
3) What happen in case that I want to add a terminal capbilities to my application (e.g telnet cli ), how should I design it ? the telnet server as a client and my console application as the server? is there a design that can help me to achieve that? CAB? I asked a lot of people and it seem that nobody is using it... is that so?
Thanks,
Eyal
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的程序应该以这样的方式设计:您可以用一个 UI 替换另一个 UI。程序应该能够具有独立于用户所看到的界面的逻辑功能。看一下 MVC 和 < a href="http://www.dofactory.com/patterns/PatternObserver.aspx" rel="nofollow noreferrer">观察者模式。
衡量程序的一个很好的方法是通过向用户提供的接口 [API 调用、基于控制台的 GUI、基于控制台的接口、网络接口、Web] 我并不是说您应该重新关注应用程序的意图使其界面非常灵活。我建议您的界面应该与应用程序的逻辑和数据存储无关。
股票行情指示器:采用观察者模式,每 200 毫秒或发生变化时广播一个新事件。股票视图将是这些事件的订阅者。
Your program should be designed in such a way that you can replace one UI with another. The program should be able to have the logic function independently from the interface that the user sees. Take a look at the MVC and Observer patterns.
One good measure of your program is through the interfaces that are made available to the user [API calls, console based GUI, console based interface, net interface, web] I'm not implying that you should refocus the intention of the application to be on making it very flexible with the interface. I'm suggesting that your interface should have nothing to do with the logic and datastore of your application.
Stock ticker: Have an oberserver pattern that broadcasts a new event every 200ms, or on changes. The ticker view would be a subscriber of these events.
为什么不将“大脑”创建为图书馆呢? WinForms 界面和控制台应用程序都是用户界面,应该与逻辑分开。
这使得您可以更轻松地访问功能,并且您还可以订阅事件。
Why don't you create the "brain" as a library? Both a WinForms interface and a console app are user interfaces and should be seperated from the logic.
This allows easier access to functions and you could also subscribe to events.
您应该避免您正在考虑的架构。让两个独立的进程一起工作是很复杂的。操作系统在进程之间设置了一堵大墙,以确保一个行为不当的进程不会破坏另一个进程的稳定。每个进程都有自己的内存视图,Windows(尤其是.NET)使进程共享内存变得非常困难。
您必须在进程之间建立通信通道才能使它们协同工作。管道或套接字是通常的选择,这里的思维模型是机器通过网络相互通信。这可能非常尴尬,您将拥有 Web 应用程序的所有缺点,而没有 WinForms 客户端或控制台模式应用程序的优点。它也非常不可靠,一个进程的故障很难被另一个应用程序诊断、报告和恢复。我相信您已经看到使用互联网浏览器可能出现的问题。
您可以从一个应用程序中获得您想要的内容。 System.Threading.Thread 类为您提供了与控制台模式应用程序相同的功能。使用BackgroundWorker 类或Control.Begin/Invoke() 方法让UI 显示来自大脑线程的消息相当简单。只是“相当”顺便说一句,获得正确的线程互操作仍然是一项努力。
有两种方法可以实现股票代码更新。推与拉方法。推送方法是让后台线程主动通知 UI 线程有可用更新。 BackgroundWorker.ReportProgress 或 Control.Begin/Invoke 即可执行此操作。在 200 毫秒更新时,这不是问题。
在这样的速度下,拉动模型也能发挥同样的作用。您可以在 UI 中使用计时器来获取定期运行的方法。它可以从计时器的 Tick 方法中的共享属性中读取值。您需要在后台线程和 Tick 方法中使用 lock 语句,以确保该值不会在 UI 线程读取该值时发生更改。
当值变化非常快时,您应该倾向于使用拉取模型,当更新 UI 所需的时间比后台线程更新之间的时间间隔长时,以一定的速率推动 UI 线程就会陷入瘫痪。 UI 线程将落后并且无法完成其正常职责。冻结的 UI 是诊断,OOM 是最终结果。 200 毫秒应该不是问题,除非您对 UI 更新非常花哨或马虎,否则推送应该可以工作。
我必须加入您咨询过有关远程登录服务器的朋友联盟。不确定它们解决了什么问题,它们相当于 1990 年的 Web 服务器,当时每个人都使用绿屏终端与计算机交谈。它可能适用于将单独的控制台模式应用程序连接到 UI 应用程序的需要。您不会使用 telnet 来执行此操作,套接字是通用通道。 .NET Remoting,或者更好的是,WCF 是位于该通道之上的层,以避免必须处理通过字节管道压缩数据或方法参数的复杂情况。如果您已经完全陷入多进程解决方案中,请遵循这一点。你不应该使用股票报价应用程序,如果没有人在场,没有人会关心它们的报价方式。也许是森林里倒下的树。
You should avoid the architecture you are contemplating. Getting two separate processes to work together is complicated. The operating system puts up a big wall between processes to make sure that one misbehaving process cannot destabilize another. Processes each have their own view of memory, Windows (and .NET especially) makes it very difficult for processes to share memory.
You'd have to establish a communication channel between processes to get them to work together. A pipe or a socket is the usual choice, the mental model here is of machines talking to each other over a network. This can be very awkward, you'd have all of the disadvantages of a web application, none of the advantages of a WinForms client or console mode app. It is also very unreliable, failure of one process is hard to diagnose, report and recover from by the other app. I'm sure you've seen what can go wrong from using your Internet browser.
You can get what you want from one application. The System.Threading.Thread class gives you the moral equivalent of your console mode app. Getting the UI to display messages from the brain thread is fairly simple with the BackgroundWorker class or the Control.Begin/Invoke() method. Only "fairly" btw, getting thread interop right is still an effort.
There are two ways to get the stock ticker update implemented. The push vs the pull approach. The push approach is letting the background thread actively notify the UI thread that an update is available. BackgroundWorker.ReportProgress or Control.Begin/Invoke to do that. At 200 msec updates, this is not a problem.
At rates like this, the pull model will work just as well. You'd use a Timer in the UI to get a method to run periodically. It could read the value from a shared property in the timer's Tick method. You'll need to use the lock statement in both the background thread and the Tick method to ensure that the value cannot change just as the UI thread is reading the value.
You should favor the pull model when the value can change very rapidly, pushing at a rate that will bring the UI thread to its knees when the time needed to update the UI is longer than the period between updates from the background thread. The UI thread will fall behind and doesn't get around to its normal duties. A frozen UI is the diagnostic, OOM is the end result. 200 msec should not be a problem unless you get very fancy or sloppy with your UI updates, push should work.
I'll have to join the league of friends you consulted about telnet servers. Not sure what problem they solve, they are the 1990 equivalent of a web server when everybody was using a green screen terminal to talk to a computer. It perhaps applies to the need of connecting a separate console mode app to a UI app. You wouldn't use telnet to do that, a socket is a generic channel. .NET Remoting or, better, WCF is the layer that sits on top of that channel to avoid having to deal with the complications of squeezing data or method parameters through a pipe of bytes. Pursue that if you are completely boxed into a multi-process solution already. You shouldn't be for a stock ticker app, nobody cares which way they tick if there isn't anybody there to look at them. Falling tree in the forest, perhaps.