English 中文(简体)
Calling DoEvents in Application.Idle
原标题:

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.

最佳回答

What you re doing here looks a lot like Cooperative multitasking. It s an interesting idea but I would say that you should really use multi threading for something like this. .NET has a lot of helper systems like Task.Factory.StartNew() and the TPL libraries that really make it easy.

I would advise against it.

To be clear though: I do not have a clear reason against it. As with a lot of areas concerning programming: if it works, it works. However, you are mixing things together that should not be mixed together, specifically background tasks and UI tasks. I believe that when you separate the background tasks and start go get your hands dirty with multi threading, thread pools, background tasks and TPL, you ll quickly see that it does work and makes life easier in the long run.

问题回答

暂无回答




相关问题
Manually implementing high performance algorithms in .NET

As a learning experience I recently tried implementing Quicksort with 3 way partitioning in C#. Apart from needing to add an extra range check on the left/right variables before the recursive call, ...

Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

How do I compare two decimals to 10 decimal places?

I m using decimal type (.net), and I want to see if two numbers are equal. But I only want to be accurate to 10 decimal places. For example take these three numbers. I want them all to be equal. 0....

Exception practices when creating a SynchronizationContext?

I m creating an STA version of the SynchronizationContext for use in Windows Workflow 4.0. I m wondering what to do about exceptions when Post-ing callbacks. The SynchronizationContext can be used ...

Show running instance in single instance application

I am building an application with C#. I managed to turn this into a single instance application by checking if the same process is already running. Process[] pname = Process.GetProcessesByName("...

How to combine DataTrigger and EventTrigger?

NOTE I have asked the related question (with an accepted answer): How to combine DataTrigger and Trigger? I think I need to combine an EventTrigger and a DataTrigger to achieve what I m after: when ...

热门标签