在Windows窗体应用程序中,我想将GUI与逻辑分开。用户请求很复杂并且涉及通信,因此我不希望它依赖于GUI线程。结构应该是这样的:
GUI -----> splash screen ---------> User Form --------------> ... | # | create Manager thread | Show this Form # | Manager -----> Check user type -------> Wait for user command --> ...
对于像这样的设计,您有哪些建议,指南或模式?这是正确的选择吗?谢谢!
修改 Manager线程应该控制GUI而不是相反。此外,Manager线程应在所有应用程序时间内生效。
答案 0 :(得分:4)
传统上这样的工作是使用BackgroundWorker
完成的基本上它是一个简单的类,它使您能够在工作线程上执行函数,然后在该函数完成后自动调用回UI线程。在运行该功能期间,UI被解锁并可以显示进度消息,或处理其他用户输入(例如取消)。
结果类似于你的模式,但是为每个任务创建并销毁了一个单独的线程(好吧,真的有池......)。
UI thread ---> Show splashscreen------------------->Show window------- | |return to UI | | create background worker | | -> Process user ------------ ->Perform query etc.
好的,根据您的评论:
你可以使用这样的模式,这是一个简单的事件案例。授予管理员UI访问权限,以便它可以对其执行方法调用,并在任务完成时注册事件(this link显示.NET中异步操作的两种主要模式)。在管理器内部,您需要维护一个可以在单个线程上按顺序执行的任务列表,并确保正确调用被调用以将结果返回到UI的事件,以便在主UI线程上运行(基本上重新创建后台工作者模式)。
我不确定你希望通过这样做获得什么,是否有理由将应用程序限制为两个线程?您是否担心创建后台工作者的成本?你需要某种查询队列系统吗?您问题中图表中的示例似乎并不需要这种模式的复杂性。
答案 1 :(得分:2)
您应该使用background worker来完成任务。
它有非常方便的事件。 DoWork和RunWorkerCompleted,非常方便。
您也可以尝试使用Threads,它们看起来像这样: (请记住,当您使用Threads时,如果您想使用UI Thread进行任何操作,则必须使用Invoke(),否则您将收到CrossThreadException)
private delegate void MyFunctionCaller();
//This will set up your worker thread and set it off
private void SetThreadToDoWork()
{
ThreadStart threadStart = new ThreadStart(DoWork);
Thread MyThread = new Thread(threadStart);
MyThread.Start();
ShowSplashScreen();
}
private void DoWork()
{
DoMyWork();
WorkCompleted();
}
private void WorkCompleted()
{
if (InvokeRequired == true)
{
MyFunctionCaller InvokeCall = delegate { WorkCompleted(); };
Invoke(InvokeCall);
}
else
{
//Back to the UI thread now.
}
}
OPs编辑
您可以在任何地方创建线程,一旦启动就可以完成多个功能。但请记住,如果您想完成UI线程只能完成的任何工作,您需要Invoke(),否则您将获得CrossThreadException。
答案 2 :(得分:1)
我开发了一个类似的项目。 GUI在不同的线程上启动管理器。 Manager有一些方法可以从GUI获取命令。 GUI正在监听Manager的事件,因此仅在Manager启动事件时才会更新。 为了避免交叉线程,我习惯于“调用”方法