Use of Application.DoEvents()

2018-12-30 23:43发布

Can Application.DoEvents() be used in C#?

Is this function a way to allow the GUI to catch up with the rest of the app, in much the same way that VB6's DoEvents does?

9条回答
不再属于我。
2楼-- · 2018-12-31 00:09

I've seen many commercial applications, using the "DoEvents-Hack". Especially when rendering comes into play, I often see this:

while(running)
{
    Render();
    Application.DoEvents();
}

They all know about the evil of that method. However, they use the hack, because they don't know any other solution. Here are some approaches taken from a blog post by Tom Miller:

  • Set your form to have all drawing occur in WmPaint, and do your rendering there. Before the end of the OnPaint method, make sure you do a this.Invalidate(); This will cause the OnPaint method to be fired again immediately.
  • P/Invoke into the Win32 API and call PeekMessage/TranslateMessage/DispatchMessage. (Doevents actually does something similar, but you can do this without the extra allocations).
  • Write your own forms class that is a small wrapper around CreateWindowEx, and give yourself complete control over the message loop. -Decide that the DoEvents method works fine for you and stick with it.
查看更多
余欢
3楼-- · 2018-12-31 00:09

I saw jheriko's comment above and was initially agreeing that I couldn't find a way to avoid using DoEvents if you end up spinning your main UI thread waiting for a long running asynchronous piece of code on another thread to complete. But from Matthias's answer a simple Refresh of a small panel on my UI can replace the DoEvents (and avoid a nasty side effect).

More detail on my case ...

I was doing the following (as suggested here) to ensure that a progress bar type splash screen (How to display a "loading" overlay...) updated during a long running SQL command:

IAsyncResult asyncResult = sqlCmd.BeginExecuteNonQuery();
while (!asyncResult.IsCompleted)  //UI thread needs to Wait for Async SQL command to return
{
      System.Threading.Thread.Sleep(10); 
      Application.DoEvents();  //to make the UI responsive
}

The bad: For me calling DoEvents meant that mouse clicks were sometimes firing on forms behind my splash screen, even if I made it TopMost.

The good/answer: Replace the DoEvents line with a simple Refresh call to a small panel in the centre of my splash screen, FormSplash.Panel1.Refresh(). The UI updates nicely and the DoEvents weirdness others have warned of was gone.

查看更多
初与友歌
4楼-- · 2018-12-31 00:16

Application.DoEvents can create problems, if something other than graphics processing is put in the message queue.

It can be useful for updating progress bars and notifying the user of progress in something like MainForm construction and loading, if that takes a while.

In a recent application I've made, I used DoEvents to update some labels on a Loading Screen every time a block of code is executed in the constructor of my MainForm. The UI thread was, in this case, occupied with sending an email on a SMTP server that didn't support SendAsync() calls. I could probably have created a different thread with Begin() and End() methods and called a Send() from their, but that method is error-prone and I would prefer the Main Form of my application not throwing exceptions during construction.

查看更多
大哥的爱人
5楼-- · 2018-12-31 00:17

Yes, there is a static DoEvents method in the Application class in the System.Windows.Forms namespace. System.Windows.Forms.Application.DoEvents() can be used to process the messages waiting in the queue on the UI thread when performing a long-running task in the UI thread. This has the benefit of making the UI seem more responsive and not "locked up" while a long task is running. However, this is almost always NOT the best way to do things. According to Microsoft calling DoEvents "...causes the current thread to be suspended while all waiting window messages are processed." If an event is triggered there is a potential for unexpected and intermittent bugs that are difficult to track down. If you have an extensive task it is far better to do it in a separate thread. Running long tasks in a separate thread allows them to be processed without interfering with the UI continuing to run smoothly. Look here for more details.

Here is an example of how to use DoEvents; note that Microsoft also provides a caution against using it.

查看更多
萌妹纸的霸气范
6楼-- · 2018-12-31 00:25

From my experience I would advise great caution with using DoEvents in .NET. I experienced some very strange results when using DoEvents in a TabControl containing DataGridViews. On the other hand, if all you're dealing with is a small form with a progress bar then it might be OK.

The bottom line is: if you are going to use DoEvents, then you need to test it thoroughly before deploying your application.

查看更多
不流泪的眼
7楼-- · 2018-12-31 00:27

Check out the MSDN Documentation for the Application.DoEvents method.

查看更多
登录 后发表回答