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?
Hmya, the enduring mystique of DoEvents(). There's been an enormous amount of backlash against it, but nobody ever really explains why it is "bad". The same kind of wisdom as "don't mutate a struct". Erm, why does the runtime and the language supports mutating a struct if that's so bad? Same reason: you shoot yourself in the foot if you don't do it right. Easily. And doing it right requires knowing exactly what it does, which in the case of DoEvents() is definitely not easy to grok.
Right off the bat: almost any Windows Forms program actually contains a call to DoEvents(). It is cleverly disguised, however with a different name: ShowDialog(). It is DoEvents() that allows a dialog to be modal without it freezing the rest of the windows in the application.
Most programmers want to use DoEvents to stop their user interface from freezing when they write their own modal loop. It certainly does that; it dispatches Windows messages and gets any paint requests delivered. The problem however is that it isn't selective. It not only dispatches paint messages, it delivers everything else as well.
And there's a set of notifications that cause trouble. They come from about 3 feet in front of the monitor. The user could for example close the main window while the loop that calls DoEvents() is running. That works, user interface is gone. But your code didn't stop, it is still executing the loop. That's bad. Very, very bad.
There's more: The user could click the same menu item or button that causes the same loop to get started. Now you have two nested loops executing DoEvents(), the previous loop is suspended and the new loop is starting from scratch. That could work, but boy the odds are slim. Especially when the nested loop ends and the suspended one resumes, trying to finish a job that was already completed. If that doesn't bomb with an exception then surely the data is scrambled all to hell.
Back to ShowDialog(). It executes DoEvents(), but do note that it does something else. It disables all the windows in the application, other than the dialog. Now that 3-feet problem is solved, the user cannot do anything to mess up the logic. Both the close-the-window and start-the-job-again failure modes are solved. Or to put it another way, there is no way for the user to make your program run code in a different order. It will execute predictably, just like it did when you tested your code. It makes dialogs extremely annoying; who doesn't hate having a dialog active and not being able to copy and paste something from another window? But that's the price.
Which is what it takes to use DoEvents safely in your code. Setting the Enabled property of all your forms to false is a quick and efficient way to avoid problems. Of course, no programmer ever actually likes doing this. And doesn't. Which is why you shouldn't use DoEvents(). You should use threads. Even though they hand you a complete arsenal of ways to shoot your foot in colorful and inscrutable ways. But with the advantage that you only shoot your own foot; it won't (typically) let the user shoot hers.
The next versions of C# and VB.NET will provide a different gun with the new await and async keywords. Inspired in small part by the trouble caused by DoEvents and threads but in large part by WinRT's API design that requires you to keep your UI updated while an asynchronous operation is taking place. Like reading from a file.
It can be, but it's a hack.
See Is DoEvents Evil?.
Direct from the MSDN page that thedev referenced:
Calling this method causes the current
thread to be suspended while all
waiting window messages are processed.
If a message causes an event to be
triggered, then other areas of your
application code may execute. This can
cause your application to exhibit
unexpected behaviors that are
difficult to debug. If you perform
operations or computations that take a
long time, it is often preferable to
perform those operations on a new
thread. For more information about
asynchronous programming, see
Asynchronous Programming Overview.
So Microsoft cautions against its use.
Also, I consider it a hack because its behavior is unpredictable and side effect prone (this comes from experience trying to use DoEvents instead of spinning up a new thread or using background worker).
There is no machismo here - if it worked as a robust solution I would be all over it. However, trying to use DoEvents in .NET has caused me nothing but pain.
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.
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.
Yes.
However, if you need to use Application.DoEvents, this is mostly an indication of a bad application design. Perhaps you'd like to do some work in a separate thread instead?
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.
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.
Check out the MSDN Documentation for the Application.DoEvents method.
The DoEvents does allow the user to click around or type and trigger other events, and background threads are a better approach.
However, there are still cases where you may run into issues that require flushing event messages. I ran into a problem where the RichTextBox control was ignoring the ScrollToCaret() method when the control had messages in queue to process.
The following code blocks all user input while executing DoEvents:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Integrative.Desktop.Common
{
static class NativeMethods
{
#region Block input
[DllImport("user32.dll", EntryPoint = "BlockInput")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool BlockInput([MarshalAs(UnmanagedType.Bool)] bool fBlockIt);
public static void HoldUser()
{
BlockInput(true);
}
public static void ReleaseUser()
{
BlockInput(false);
}
public static void DoEventsBlockingInput()
{
HoldUser();
Application.DoEvents();
ReleaseUser();
}
#endregion
}
}
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.
Related
I am pretty sure Applicataion.DoEvents() in Windows Forms. is a very early, very primitive, WindowsForms only form of Multitasking. It has all the telltales and mechanics:
Pausing execution of the calling Event.
Making the rest of said Event a continuation to be run later.
Allowing the other Events/Processes to run. Just with some extra issues, because the MT is implemented via the EventQueue. Possibly even a recursive call to the Queue.
But I just ran into a person that insists it has "nothing to do with Multitasking", which I cannot reconcile with my understanding of the Function or the of Multitasking.
Note: I explicitly consider Mutltithreading only an implementation for Multitasking. It is clear that DoEvents() is not a form of Multithreading, as we all know how poorly that one works in GUI Environments.
I am pretty sure it is a very early, very primitive, Windows Forms only form of Multitasking
You are pretty close to correct on all counts except for your conjecture that it is for WinForms only. "DoEvents" precedes WinForms; it was present in Visual Basic long before WinForms was invented, and "pump the message queue" obviously precedes VB also. And it was a bad idea and easily abused then too.
Making the rest of said Event a continuation to be run later.
DoEvents doesn't really make anything into a continuation the way that say, await does. Whatever event is currently "in flight" when DoEvents is called has its state on the stack, and the stack is the implementation of continuation in this case. This is another point against DoEvents -- unlike await, it eats stack, and therefore can contribute to an overflow.
I just ran into a poster that insists it has "nothing to do with Multitasking".
You should ask the author for clarification then, since that certainly sounds wrong.
Well, it's called Preemptive Multitasking, meaning "interrupting a task". You do multiple Tasks, but never two at the same time. It's not about using multiple cores of the CPU, but a way to control multiple activities inside your program.
Common Sample is, to give the program a chance to handle mouse movement by the user, while doing a lengthy operation, running something that can be considered a "batch"-job.
Normally you don't have to care about this "DoEvents", but if you know, you have a procedure running for more than 1 second, you should call it manually, you pass the control to another method thereby, you stop your own code, let other code run, and than you continue with your own code.
So it's never asynchronous, but still some kind of "multitasking".
It's more a control structure, the important thing is, you do not know what's going on inside, you call it "just for case" - somebody else might need the CPU for a millisecond.
There is no external task scheduler interrupting your code and doing a context switch, you have to "behave" by interrupting your code yourself, if you do something lengthy. It is a convention that you do only "small" things in event handlers and return the control to Windows as soon as possible,either by finishing the method, or by calling DoEvents.
I'm new in C# and I'm using System.Threading.
I have this code:
UISystem.SetScene(Scene_Menu);
Thread.Sleep (9000);
p.Text="HELLO";
Thread.Sleep(9000);
p.Text="WORLD";
It delays 18 seconds, but the p.Text="HELLO" doesn't show between the sleep functions. What's the problem with my code?
Thanks.
Timers don't work since I can't edit p from a separate thread.
Application.DoEvents() is a Windows Forms function, I'm building an application in PS Vita.
You have discovered why you should never use Thread.Sleep. It is useful for only two things. (1) Writing test cases that need to simulate a thread being busy for a certain number of seconds, and (2) Sleeping for zero milliseconds tells the operating system "I cede the rest of my time slice to another process if there exists one that wants it"; it's a politeness thing.
You should never use thread.Sleep to introduce a delay as you are doing for exactly the reason you have discovered. You are setting a property, but setting a property does not cause the operating system to repaint the screen. Consider if it did; you might have a thousand property sets in a method, and you would have to repaint the screen after all of them, which would look ugly and be very slow.
Instead what happens is the property is set and the object makes a note to the operating system that says when this thread is available to handle operating system messages again, please repaint me. Your program is, instead of telling the operating system "I'm done, go ahead and see if there are any message for me" that instead you want the thread to do nothing for nine seconds.
Now, you can tell the program to check for messages by calling DoEvents but using DoEvents is also a bad idea and you should not do it. Doing so essentially causes your program to exhibit symptoms of Attention Deficit Disorder; you have not finished the current job and you are looking to see if there are new jobs to do without removing the old jobs from the call stack! Suppose those new jobs in turn get interrupted, and so on, and so on. The stack grows without bound, which is very bad. DoEvents is a "worst practice", just like sleeping a thread. You can get away with it in small simple programs but it leads to big trouble when the program becomes complex.
Moreover: yes, DoEvents will paint your control, but that is all it will do. For the next nine seconds, the application will appear to the user to be completely hung. That is a very bad user experience.
The right thing to do if you want to introduce a delay is to asynchronously wait. In C# 4 and earlier the standard way to do that is to create a timer, and when the timer ticks, do the next thing.
Now, you say that you cannot use a timer because you need to access the control from the UI thread. That's fine. The timer's tick event handler will run on the UI thread, not on a separate thread. You can safely use a timer.
In C# 5, the right thing to do is to use the new await keyword to introduce an asynchronous wait. That is, a wait that does other stuff while it is waiting, instead of going to sleep while it is waiting. In C# 5 you would write your code as:
UISystem.SetScene(Scene_Menu);
await Task.Delay (9000);
p.Text="HELLO";
await Task.Delay(9000);
p.Text="WORLD";
C# 5 is at present in beta; for details on this new feature see:
http://msdn.microsoft.com/en-us/async
For a gentle introduction to async and an explanation of why DoEvents is bad news, see my MSDN magazine article:
http://msdn.microsoft.com/en-us/magazine/hh456401.aspx
I know there are other questions around this but most end up with the answer don't do what I am about to suggest. So I know you aren't supposed to. The reason for this question is I want to do it anyway, how can I do it...
Here is why I want to break the rules...
Let's say I have a complicated application, it's version 1 and we want our customers to submit errors to us in the event of crashes or hangs. Let's now say I have a button on the top of the main form they click to submit reports.
Let's now imagine that the application hung because of a deadlock...
It would be nice if that small piece of UI and a handler for that button could live on a thread other than the main ui thread so that it isn't caught up in the deadlock. When clicked it would gather all the call stacks for the other threads and submit them to our error reporting service.
Now, knowing the scenario, can this be done in .net?
Yes, there is no magic in creating UI on another thread than the "main thread". The important rule to always keep in mind is to interact with that UI on the thread that created it.
Still, I feel that you are attacking this from the wrong angle. You should probably instead make an effort to push all work off the main thread. That way you minimize the risk for that thread to freeze, and then you don't need to resort to unorthodox solutions for the error reporting.
I have various cases of creating forms on non-main thread, and it works fine every time.
Create a new Thread, and show a Form from it. New message loop will be created for that thread and everything will run fine.
What magic will you use to gather data from the crashed app and locked main thread, that's up to you :)
if application hung, your main message loop is dead, thus ui will not work. As workaround for your problem i'd consider usage of external application (another exe) which will be invoked in case of report
in any case, if you want to invoke UI from other thread you should perform context switch In case of winforms, follow this answer
It sounds like you'd like to keep the UI alive, even when some other operation is mired in a deadlock. If so, perhaps Asynchronous Programming would be of use. Using Async to manage a potentially hung up task would allow the remainder of the application to remain responsive.
we want our customers to submit errors to us in the event of crashes or hangs
You might also consider adding some degree if instrumentation/reporting, so that you'll have this data without requiring user input.
I'm doing all this in C#, in Visual Studio 2008.
I want to slow down the work of my algorithm so that the user can watch it's work. There is a periodic change visible at the GUI so I added Thread.Sleep after every instance.
Problem is that Thread.Sleep, when set to at least a second, after a few instances of Thread.Sleep (after few loops) simply freezes entire GUI and keeps it that way till program completion. Not right away, but it always happens. How soon depends on the length of the sleep.
I have proof that entire program does not freeze, it's working it's thing, even the sleep is making pauses of correct length. But the GUI freezes at certain point until the algorithm ends, at which point it shows the correct final state.
How to solve this issue? Alternative to pausing algorithm at certain point?
First off, don't make the user wait for work that is done before they even think about when it will be finished. Its pointless. Please, just say no.
Second, you're "sleeping" the UI thread. That's why the UI thread is "locking up." The UI thread cannot be blocked; if it is, the UI thread cannot update controls on your forms and respond to system messages. Responding to system messages is an important task of the UI thread; failing to do so makes your application appear locked up to the System. Not a good thing.
If you want to accomplish this (please don't) just create a Timer when you start doing work that, when it Ticks, indicates its time to stop pretending to do work.
Again, please don't do this.
I'd guess everything is running out of a single thread. The user probably invokes this algorithm by clicking on a button, or some such. This is handled by your main thread's message queue. Until this event handler returns, your app's GUI cannot update. It needs the message queue to be pumped on regular basis in order to stay responsive.
Sleeping is almost never a good idea, and definitely not a good idea in the GUI thread. I'm not going to recommend that you continue to use sleep and make your GUI responsive by calling Application.DoEvents.
Instead, you should run this algorithm in a background thread and when it completes it should signal so to the main thread.
You are about to commit some fairly common user interface bloopers:
Don't spam the user with minutiae, she's only interested in the result
Don't force the user to work as fast as you demand
Don't forbid the user to interact with your program when you are busy.
Instead:
Display results in a gadget like a ListBox to allow the user to review results at her pace
Keep a user interface interactive by using threads
Slow down time for your own benefit with a debugger
This depends on a lot of things, so its hard to give a concrete answer from what you've said. Still, here are some matters that might be relevant:
Are you doing this on a UI thread (e.g. the thread the form-button or UI event that triggered the work started on)? If so, it may be better to create a new thread to perform the work.
Why do you sleep at all? If the state related to the ongoing work is available to all relevant threads, can the observer not just observe this without the working thread sleeping? Perhaps the working thread could write an indicator of the current progress to a volatile or locked variable (it must be locked if it's larger than pointer size - e.g. int or an object - but not otherwise. If not locked, then being volatile will prevent cache inconsistency between CPUs, though this may not be a big deal). In this case you could have a forms timer (there are different timers in .Net with different purposes) check the status of that variable and update the UI to reflect the work being done, without the working thread needing to do anything. At most it may be beneficial to Yield() in the working thread on occasion, but its not likely that even this will be needed.
I want to paralelize a 3D voxel editor built on top of Windows Forms, it uses a raycaster to render so dividing the screen and getting each thread on a pool to render a part of it should be trivial.
The problem arises in that Windows Forms' thread must run as STA - I can get other threads to start and do the work but blocking the main thread while waiting for them to finish causes strange random deadlocks as expected.
Keeping the main thread unblocked would also be a problem - if, for example, the user uses a floodfill tool the input would be processed during the rendering process which would cause "in-between" images (an object partially colored, for example). Copying the entire image before every frame isn't doable either because the volumes are big enough to offset any performance gain if it has to be copied every frame.
I want to know if there is any workaround to get the amin thread to appear blocked to the user in a way that it will not be actually blocked but will delay the processing of input till the next frame.
If it isn't possible, is there a better design for dealing with this?
EDIT: Reading the anwsers I think I wasn't clear that the raycaster runs in real time, so showing progress dialogs won't work at all. Unfortunately the FPS is low enough (5-40 depending on various factors) for the input between frames to produce unwanted results.
I have already tried to implement it blocking the UI thread and using some threads of a ThreadPool to process and it works fine except for this problem with STA.
This is a common problem. With windows forms you can have only one UI thread. Don't run your algorithm on the UI thread because then the UI will appear frozen.
I recommend running your algorithm and waiting for it to finish before updating the UI. A class called BackgroundWorker comes pre-built to do just this very thing.
Edit:
Another fact about the UI thread is that it handles all of the mouse and keyboard events, along with system messages that are sent to the window. (Winforms is really just Win32 surrounded by a nice API.) You cannot have a stable application if the UI thread is saturated.
On the other hand, if you start several other threads and try to draw directly on the screen with them, you may have two problems:
You're not supposed to draw on the UI with any thread but the UI thread. Windows controls are not thread safe.
If you have a lot of threads, context switching between them may kill your performance.
Note that you (and I) shouldn't claim a performance problem until it has been measured. You could try drawing a frame in memory and swapping it in at an appropriate time. Its called double-buffering and is very common in Win32 drawing code to avoid screen flicker.
I honestly don't know if this is feasible with your target frame rate, or if you should consider a more graphics-centered library like OpenGL.
Am I missing something or can you just set your render control (and any other controls that generate input events) to disabled while you're rendering a frame? That will prevent unwanted inputs.
If you still want to accept events while you're rendering but don't want to apply them until the next frame, you should leave your controls enabled and post the detail of the event to an input queue. That queue should then be processed at the start of every frame.
This has the affect that the user can still click buttons and interact with the UI (the GUI thread does not block) and those events are not visible to the renderer until the start of the next frame. At 5 FPS, the user should see their events are processed within 400ms worst case (2 frames), which isn't quite fast enough, but better than threading deadlocks.
Perhaps something like this:
Public InputQueue<InputEvent> = new Queue<InputEvent>();
// An input event handler.
private void btnDoSomething_Click(object sender, EventArgs e)
{
lock(InputQueue)
{
InputQueue.Enqueue(new DoSomethingInputEvent());
}
}
// Your render method (executing in a background thread).
private void RenderNextFrame()
{
Queue<InputEvent> inputEvents = new Queue<InputEvent>();
lock(InputQueue)
{
inputEvents.Enqueue(InputQueue.Dequeue());
}
// Process your input events from the local inputEvents queue.
....
// Now do your render based on those events.
....
}
Oh, and do your rendering on a background thread. Your UI thread is precious, it should only do the most trivial work. Matt Brundell's suggestion of BackgroundWorker has lots of merit. If it doesn't do what you want, the ThreadPool is also useful (and simpler). More powerful (and complex) alternatives are the CCR or the Task Parallel Library.
Show a modal "Please Wait" dialog using ShowDialog, then close it once your rendering is finished.
This will prevent the user from interacting with the form while still allowing you to Invoke to the UI thread (which is presumably your problem).
If you don't want all the features offered by the BackgroundWorker you can simply use the ThreadPool.QueueUserWorkItem to add something to the thread pool and use a background thread. It would be easy to show some kind of progress while the background thread was performing it's operations as you can provide a delegate callback to notify you whenever a particular background thread is done. Take a look at ThreadPool.QueueUserWorkItem Method (WaitCallback, Object) to see what I'm referring you to. If you need something more complex you could always use the APM async method to perform your operations as well.
Either way I hope this helps.
EDIT:
Notify user somehow that changes are being made to the UI.
On a(many) background threads using the ThreadPool perform the ops you need to perform to the UI.
For each operation keep a reference to the state for the operation so that you know when it completed in the WaitCallback. Maybe put them in some type of hash / collection to keep ref to them.
Whenever an operation completes remove it from the collection that contains a ref to the ops that were performed.
Once all operations have completed (hash / collection) has no more references in it render the UI with the changes applied. Or possibly incrementally update the UI
I'm thinking that if you are making so many updates to the UI while you are performing your operations that is what is causing your problems. That's also why I recommended the use of SuspendLayout, PerformLayout as you may have been performing so many updates to the UI the main thread was getting overwhelmed.
I am no expert on threading though, just trying to think it through myself. Hope this helps.
Copying the entire image before every frame isn't doable either because the volumes are big enough to offset any performance gain if it has to be copied every frame.
Then don't copy the off-screen buffer on every frame.