我在处理CRUD操作的WinForms应用程序(VB.NET)上工作。 当它加载数据时,似乎状态为“无响应”,加载完成后,每件事都会正常。
当表单从数据库中获取记录时,如何解决类似的问题?
非常感谢。
答案 0 :(得分:5)
您可以使用BackgroundWorker在后台线程上卸载冗长的操作,以避免阻塞主UI线程。
答案 1 :(得分:2)
所有Windows应用程序都是如此,如果您从事件中执行任何长度操作,您将在一段时间内“无响应”,因为程序没有响应系统的其余部分。你有几个选择:
如果您将使用第二个选项,请确保您不直接在UI上更新任何内容,因为它会中断,而是使用Invoke()。
答案 2 :(得分:1)
如果您使用的是单一界面,则最好使用Application.DoEvents()
。如果您有一个表单在单击按钮时执行一系列任务,那么您将使用单个界面。
为什么选择Application.DoEvents()?
From the MSDN page on DoEvents():
运行Windows窗体时,它会创建新窗体,然后等待事件处理。每次表单处理事件时,它都会处理与该事件相关的所有代码。所有其他事件在队列中等待。当您的代码处理事件时,您的应用程序不会响应。例如,如果在顶部拖动另一个窗口,窗口不会重新绘制。
如果您在代码中调用DoEvents,您的应用程序可以处理其他事件。例如,如果您有一个表单将数据添加到ListBox并将DoEvents添加到您的代码中,那么当另一个窗口被拖动时,您的表单将重新绘制。如果从代码中删除DoEvents,则在按钮的单击事件处理程序执行完毕之前,表单将不会重新绘制。有关消息传递的详细信息,请参阅Windows窗体中的用户输入。
简而言之,如果您单击按钮并且必须等待完成某些工作,Application.DoEvents()
将刷新表单UI并摆脱(无响应)问题。
如何使用DoEvents() 相同的MSDN页面也说明了
通常,您在循环中使用此方法来处理消息。
因此,告诉它应该去哪里的最简单方法是在程序中寻找一个循环,在该循环中发生冗长的操作并将Application.DoEvents()
放在该循环中。我通常将它放在所述循环内的最后。
例如:
foreach (var foo in bar)
{
// Do work
Application.DoEvents();
}
为什么不使用单一界面的BackgroundWorker?
当您创建不需要多线程的多个线程时,您可能会出现线程泄漏的可能性。例如,如果您实现BackgroundWorker来处理CRUD操作,但由于某种原因,关闭程序,接口将关闭但后台工作程序线程将继续运行。您可以通过任务管理器确认此过程仍在运行。
当您有其他正在使用的设备(如打印机)时,BackgroundWorkers非常理想。也就是说,您可能不希望程序在完成打印文档之前停止;因此,在您继续使用程序时,新线程可以处理打印作业。