我要在MainForm进行一些数据库相关工作时显示带有进度栏的新表单。我读到您不想将UI传递给新线程,所以我想知道解决此问题的最佳解决方案是什么?
我无法在另一个线程上执行与数据库相关的工作,因为它使用了十二个对UI和MainForm的调用。我也不能使用Application.DoEvents()
,因为MainForm的线程正在类中工作,据我所知,您不应对类的父类进行任何调用。
任何建议,将不胜感激!
编辑
为了澄清我实际上想知道的事情:
我的程序看起来像这样:
... Content = DatabaseClass.LoadContent();
ApplyContentToUI(Content);
我想做的是以下几点:
//Show a form here with a progressbar
... Content = DatabaseClass.LoadContent();
ApplyContentToUI(Content);
//Close the form here
但是,自从执行ApplyContentToUI的时间开始就是aprox。我希望1秒钟执行以下操作:
//Show a form here with a progressbar
... Content = DatabaseClass.LoadContent();
//Close the form here
ApplyContentToUI(Content);
如果您与我不同,如果需要在重新加载UI时显示进度栏,建议您查看下面的评论和答案。
最佳答案
I can't do the database related work on another thread
错误的。
推荐:
正如许多评论中提到的那样,您应该重构代码以将业务逻辑与UI逻辑分开。每个.NET版本都有已知的模式和实践,这将导致清晰的分离。我整理了一些工具及其指向用法的链接,供您查看。
工具:
BeginInvoke
Control.BeginInvoke
方法可用于异步操作(.NET 2.0+)。 BeginInvoke
用于在控件源自的线程上异步运行代码。如果发起线程是UI线程,这将允许进行UI操作。 BackgroundWorker
使用它来ReportProgress
。这将允许UI在长时间运行的操作发生时保持响应。这不应直接嵌入业务逻辑中。但是,它可以用于将消息中继回UI线程。
看:
后台 worker
BackgroundWorker
将在单独的线程上运行工作,并且它具有事件驱动的进度(.NET 2.0+)。 BackgroundWorker
是一个事件驱动的控件,它将在另一个线程上执行代码。它具有内置的功能,可以使用 ReportProgress
向监听器通知进度。在后台
BackgroundWorker
使用Control.BeginInvoke
作为ReportProgress
,从而可以有效分离业务逻辑。看:
调度员
Dispatcher
可以将操作中继到UI线程(.NET 3.0+)。 Dispatcher
是为WPF添加的,但仍可以在WinForms中使用(尽管不太理想)。 Dispatcher
的功能与BeginInvoke
相同,并且可以同步运行或异步运行。看:
任务
Task(T)
类,可以很容易地将逻辑与UI线程交织在一起。 (带有TPL包的.NET 4.0 + 、. NET 3.5+)。 添加了任务并行库以提供一组并行性和并发性抽象。
Task
是消息驱动的,并允许封装非阻塞操作。这也是.NET 4.5 async
/await
模式的基础。Task
用于流式处理操作,以便可以将它们链接在一起并产生结果。比BackgroundWorker
更加简化,并且可以更好地进行操作组合。这也使producer-consumer scenarios的实现更加简单。看:
关于c# - 在主线程忙时连续更新UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17531106/