I don't know why you would use this quote from Dan T that is completely wrong:
DoEvents messes up the normal flow of your application. If I recall correctly, DoEvents is asynchronous which means it terminates before the application has actually processed any outstanding events
No, DoEvents is synchronous; it returns only once all outstanding events have been processed. Yes, the user might click the same button again (you should have disabled the button, duh), or perform other actions that could cause the same code to be re-entered "unexpectedly", but multithreading has the same problem, only worse: with multithreading a button can not only be clicked a second time, but if you're not very careful, the same data could be manipulated by different threads at the same time!
(I know this post is old but it's still a top Google result for ".NET DoEvents" so I feel compelled to correct this error.)
DoEvents is usually not the solution that provides the best user experience, but even in 2014, it's often still the easiest.