I stay away from Application.DoEvents, since there is the issue of re-entrancy and there is always another way to avoid holding up the UI. I ve long prefered to do background work in the Application.Idle event as a simple alternative to multi-threading. But, for long-running tasks, is it acceptable to run operations in Application.Idle with a DoEvents loop?
class LongRunningTask : IDisposable {
public LongRunningTask(IEnumerable<Tidbit> listOfDataToBeProcessed) {
Application.Idle += OnIdle;
foreach(Tidbit t in listofDataToBeProcessed) {
tidbits.Enqueue(t);
}
}
// Small pieces of data to process
Queue<Tidbit> tidbits = new Queue<Tidbit>();
void OnIdle(object sender, EventArgs e) {
while(tidbits.Count > 0) {
var tidbit = tasks.Dequeue();
tidbit.Process();
// Process any messages that have queued up
// while the data was being processed
Application.DoEvents();
}
}
public void Dispose() {
Application.Idle -= OnIdle;
}
}
The logic here is that in the Application.Idle event, where we call DoEvents, there are no messages queued, so we should not be able to re-enter code. Each tidbit would be processed quickly enough that it should not hold up the message queue (or UI) significantly.
So, is there any harm or drawback to this approach? Namely, is it safe to call DoEvents in the Idle event? I do know that C# 5 will have a feature to address this sort of situation, but for those of us who aren t using C# 5 (which is most of us at the moment), and out of general curiosity, is this a good plan? Or is there a simpler alternative to process messages during a long-running operation without resorting to multi-threading?
Please don t think that I imagine this to be a magic bullet. I know that it comes with the same pitfalls as any asynchronous approach. I am aware that one must still be able to keep his application in a consistent state. And I am aware that there are multithreaded solutions. I am avoiding those. Why? Because multi-threading is more complicated. I don t think that that s impractical.