.NET 在等待任务完成时保持应用程序处于活动状态
我刚刚继承了使用生产者-消费者模式的 ac# 4.0 WinForms 应用程序(基本上只是一个小仪表板)。我的消费者任务(字面意思是 System.Threading.Tasks.Task)正在处理队列中的数据。当用户想要关闭应用程序时,生产者(TCP 套接字服务器)会立即停止。但是,队列可能不为空,因此我需要为用户提供立即退出或消费者任务处理完所有排队数据后立即退出的选项。如果用户想要等待消费者任务完成,UI 自然需要保持响应。我遇到的问题是,由于退出应用程序的代码驻留在“退出”按钮的单击事件处理程序中,因此当我位于单击事件处理程序内时,我可能需要等待使用者任务完成。简而言之,事件处理程序包含这个(非常丑陋的)代码:
// loop while there is still data in the queue
while (QueuedData.Count > 0)
{
Application.DoEvents(); // UI is semi-responsive but with a lot of CPU utilization)
}
// the queue is empty so now exit the application
任何人都可以建议一种实现此功能的替代方法,这样我就不会陷入 UI 线程上事件处理程序内部的紧密循环中吗?此时启动另一个线程/任务来处理此检查然后从该线程关闭应用程序是否有意义?非常感谢!
I just inherited a c# 4.0 WinForms app (basically just a small dashboard) that uses a producer-consumer pattern. My consumer task (literally System.Threading.Tasks.Task) is processing data in a queue. When the user wants to shut down the app, the producer (a TCP socket server) is stopped immediately. However, the queue may not be empty so I need to give the user the option to exit immediately or exit as soon as the consumer task has finished processing all of the queued data. If the user wants to wait for the consumer task to finish, the UI naturally needs to remain responsive. The problem I'm having is that since the code to exit the application resides in the click event handler for the "Exit" button, I may need to wait for the consumer task to finish while I'm inside the click event handler. In a nutshell, the event handler contains this (very ugly) code:
// loop while there is still data in the queue
while (QueuedData.Count > 0)
{
Application.DoEvents(); // UI is semi-responsive but with a lot of CPU utilization)
}
// the queue is empty so now exit the application
Can anyone suggest an alternate way of implementing this functionality so that I'm not stuck in tight loop inside of an event handler on the UI thread? Would it make any sense to start another thread/task at this point to handle this checking and then shut down the app from that thread? Thanks very much!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以有一个退出任务在同一个队列中排队[通过“退出”按钮]
- 当队列完成时,将调用退出处理程序。
如果您愿意,您可以同时更新 UI 以显示“退出待处理...”。
You could have an Exit task that is queued in the same queue [by the Exit button]
- when the queue is finished, the Exit handler would be called.
If you wanted, you could update the UI to say 'Exit pending...' in the meantime.
处理关闭事件,取消它,向关闭表单的任务添加延续。
Handle close event, cancel it, add continuation to task that closes form.
正如您所提到的,使用这样的循环可能会占用大量 CPU 资源。为什么不充分使用观察者模式,以便:
订阅者将侦听更新并将其在 BlockingCollection(或任何其他 Blocking 集合)中排队
另一个后台线程将等待上述队列中的项目并在其出现时对其进行处理
处理shutdown:
你停止发布到队列;
您可以找出队列中有多少项目并通过 GUI 通知,以便用户可以选择等待强制关闭(如果需要)
BlockingCollection 上的 MSDN 链接
also using a loop like that might be quite CPU intensive as you have mentioned. Why not use Observer pattern to the full so that:
subscriber will listen for updates and queue it up in the BlockingCollection (or any other Blocking collection)
another background thread will wait for items in the above queue and process it as it comes along
On shutdown:
you stop publishing to the queue;
you can find out how many items you got in the queue and inform the via GUI so that user can choose to wait for force close if needed
MSDN link on BlockingCollection