2008-10-02 31 views
2

我试图做一个MVP风格的Windows窗体应用程序,并没有做过太多的线程之前,我都感到困惑。WinForms:让我的UI独立于我的BLL层运行的实现问题?

我的用户界面是一组非常简单的窗体。每个表单都实现一个接口,并包含对居住在业务逻辑层中的中介类的引用,反之亦然。 因此,作为简化框图如下:

CheckInForm : ICheckIn      <-------> CheckInMediator : ICheckInMediator 
---------------------------------------------------------------------------------------- 
CheckInForm.Show()       <-------- 
              --------> AttemptCheckIn(CheckInInfo) 
CheckInForm.DisplayCheckInInfo(DisplayInfo) <-------- 
              --------> CompleteCheckIn(AdditionalCheckInInfo) 
    PleaseWaitDialog.Show()     <-------- 
    PleaseWaitDialog.Close()     <-------- 
CheckInForm.Close()       <-------- 

正如你可以看到,中介类控制UI,告诉它时显示的数据,启动,关闭等他们甚至表示,当一个模式对话框应该出现以及何时应该关闭(即上面的PleaseWaitDialog)UI的唯一功能是在屏幕上显示数据并将输入中继到中介。

这种架构很不错,并且已经非常容易测试和原型了。现在我把它放在一起,但是我开始遇到线程问题。例如,如果我希望我的PleaseWaitDialog在CheckInForm上显示为模式窗体(使用ShowDialog()),直到由介体控制的计时器计数5秒(请记住,这是一个简化操作),则会出现交叉线程错误如果我从计时器的回调中调用PleaseWaitDialog.Close()。同样,如果我有一个模式对话框阻止用户与UI进行交互,我不希望它阻止业务层中的活动,除非我另有指定(例如使用确认对话框)。

我认为我想要做的是在主线程和UI上对完全独立的线程运行调解器和业务逻辑,我的第一个问题是这样做有意义吗?

我的第二个问题是,我该如何做一些类似于在单独的线程中运行的类?我该如何沟通?我正在通过.NET线程阅读的方式,但我有一个截止日期和一些例子,如何在主线程上产生一个类生成一个包含UI的线程,让他们的对象相互交谈可以真正帮助。

回答

2

你看过BackgroundWorker类吗?这对于在后台类型过程中进行大量简化处理非常有用,并且可以列出可以让您的GUI显示进度的事件。

+0

我已经看过它,但一定不了解所有那些以及如何在这种情况下工作。你能进一步解释吗? – 2008-10-03 13:02:21

+0

在上面的示例中,您将使用BackgroundWorker选项使您的DisplayCheckinInfo方法触发CompleteCheckIn方法。这样完整的检查处理可以在单独的线程中发射,然后您可以跟踪它的进度并相应地更新对话框。 – 2008-10-03 15:26:05

0

从另一个线程可以操纵WinForms控件,但你需要使用Control.Invoke(),你会付出相当大的性能损失,每跨线程调用,由于上下文切换和幕后的CLR相关巫毒教。

如果要在多线程应用程序中将GUI从业务逻辑和基础架构代码中分离出来,建议使用线程安全队列切换到消息传递模型。每当较低层需要告诉GUI执行某些操作时,它们将一个消息对象放入一个队列中,GUI元素通过一个​​定期轮询。这对大型处理器密集型应用程序尤其适用,因为您可以通过调整更新计时器频率来在某种程度上扼制GUI更新的处理需求。

对于以另一种方式返回的调用(GUI - > lower layers),只要调用那些调用合理快速的调用即可调用mediator方法 - 您需要非常小心地延迟GUI线程,因为整个应用程序的响应将受到影响。如果您有一些呼叫很难快速返回,您可以添加另一个队列。