I have a form with buttons, textBoxes and userControls on it. When a button is clicked, it calls a method in another class. In this class a Message box opens. When user clicks OK, the messageBox closes, and the class method proceeds for 10 or so seconds before ending. During this 10 seconds, what ever textBox, or button the message box was over still displays the messageBox (They are not getting repainted).
我有一个带有按钮,textBoxes和userControls的表单。单击按钮时,它会调用另一个类中的方法。在此类中,将打开一个消息框。当用户单击“确定”时,messageBox将关闭,并且类方法将在结束前持续10秒左右。在这10秒钟内,消息框所在的textBox或按钮仍然显示messageBox(它们没有重新绘制)。
The question is how can I force everything to repaint on the form. The problem is the class that has the messageBox does not have any knowledge of the form that called it
问题是我如何强制在表格上重绘一切。问题是具有messageBox的类不具有调用它的表单的任何知识
Frank
5 个解决方案
#1
You can try with
你可以试试
Application.DoEvents()
right after the message box closes. However - unless you execute the method that you are calling in that other class in a background thread - your UI will not be responsive for 10 seconds.
消息框关闭后。但是 - 除非您在后台线程中执行您在其他类中调用的方法 - 否则您的UI将无法响应10秒。
#2
Is that 10 seconds spent doing work entirely in the UI? If not, it should really be done on a separate thread. Even if you refresh the form itself, you're still going to have a unresponsive UI for 10 seconds, which isn't ideal.
完全在UI中完成工作需要10秒吗?如果没有,它应该在一个单独的线程上完成。即使您自己刷新表单,您仍然会在10秒内没有响应的UI,这并不理想。
See my threading tutorial for an example of executing code in a different thread and calling back to the UI thread. Be aware that this is the "old" way of doing things - BackgroundWorker makes things somewhat simpler.
有关在不同线程中执行代码并回调UI线程的示例,请参阅我的线程教程。请注意,这是“旧”的做事方式 - BackgroundWorker使事情变得更简单。
#3
The problem here is that you have processing that is occurring on the UI thread and blocking the paint message. Calling Refresh or Invalidate isn't going to fix this, as you are still blocking on the thread that would perform those operations.
这里的问题是您在UI线程上进行了处理并阻止了绘制消息。调用Refresh或Invalidate不会解决这个问题,因为您仍在阻塞执行这些操作的线程。
Rather, you should take that processing and move it to another thread, and then update your UI thread (appropriately, through the Invoke method, more likely than not) as you perform the work on the background thread.
相反,你应该进行处理并将其移动到另一个线程,然后在后台线程上执行工作时更新你的UI线程(适当地,通过Invoke方法,更有可能)。
#4
To force everything to repaint you can call Invalidate() on the main form.
要强制重绘所有内容,可以在主窗体上调用Invalidate()。
#5
Your problem is that you are doing your work on the UI thread. The UI will not get repainted until your method returns which will allow the Windows message loop to continue.
您的问题是您正在UI线程上工作。在您的方法返回之前,UI不会重新绘制,这将允许Windows消息循环继续。
The solution is to run your work method on a different thread. Perhaps the BackgroundWorker class will solve your problem nicely.
解决方案是在不同的线程上运行您的工作方法。也许BackgroundWorker类可以很好地解决您的问题。
Edit: See this article for an in depth explanation:
http://www.yoda.arachsys.com/csharp/threads/winforms.shtml
编辑:有关详细说明,请参阅此文章:http://www.yoda.arachsys.com/csharp/threads/winforms.shtml
#1
You can try with
你可以试试
Application.DoEvents()
right after the message box closes. However - unless you execute the method that you are calling in that other class in a background thread - your UI will not be responsive for 10 seconds.
消息框关闭后。但是 - 除非您在后台线程中执行您在其他类中调用的方法 - 否则您的UI将无法响应10秒。
#2
Is that 10 seconds spent doing work entirely in the UI? If not, it should really be done on a separate thread. Even if you refresh the form itself, you're still going to have a unresponsive UI for 10 seconds, which isn't ideal.
完全在UI中完成工作需要10秒吗?如果没有,它应该在一个单独的线程上完成。即使您自己刷新表单,您仍然会在10秒内没有响应的UI,这并不理想。
See my threading tutorial for an example of executing code in a different thread and calling back to the UI thread. Be aware that this is the "old" way of doing things - BackgroundWorker makes things somewhat simpler.
有关在不同线程中执行代码并回调UI线程的示例,请参阅我的线程教程。请注意,这是“旧”的做事方式 - BackgroundWorker使事情变得更简单。
#3
The problem here is that you have processing that is occurring on the UI thread and blocking the paint message. Calling Refresh or Invalidate isn't going to fix this, as you are still blocking on the thread that would perform those operations.
这里的问题是您在UI线程上进行了处理并阻止了绘制消息。调用Refresh或Invalidate不会解决这个问题,因为您仍在阻塞执行这些操作的线程。
Rather, you should take that processing and move it to another thread, and then update your UI thread (appropriately, through the Invoke method, more likely than not) as you perform the work on the background thread.
相反,你应该进行处理并将其移动到另一个线程,然后在后台线程上执行工作时更新你的UI线程(适当地,通过Invoke方法,更有可能)。
#4
To force everything to repaint you can call Invalidate() on the main form.
要强制重绘所有内容,可以在主窗体上调用Invalidate()。
#5
Your problem is that you are doing your work on the UI thread. The UI will not get repainted until your method returns which will allow the Windows message loop to continue.
您的问题是您正在UI线程上工作。在您的方法返回之前,UI不会重新绘制,这将允许Windows消息循环继续。
The solution is to run your work method on a different thread. Perhaps the BackgroundWorker class will solve your problem nicely.
解决方案是在不同的线程上运行您的工作方法。也许BackgroundWorker类可以很好地解决您的问题。
Edit: See this article for an in depth explanation:
http://www.yoda.arachsys.com/csharp/threads/winforms.shtml
编辑:有关详细说明,请参阅此文章:http://www.yoda.arachsys.com/csharp/threads/winforms.shtml