代码之家  ›  专栏  ›  技术社区  ›  snarf

在应用程序中调用DoEvents.Idle

  •  1
  • snarf  · 技术社区  · 15 年前

    我远离Application.DoEvents,因为存在重新进入的问题,而且总是有另一种方法可以避免耽搁UI。我一直喜欢在Application.Idle事件中做后台工作,作为多线程的简单替代。但是,对于长时间运行的任务,是否可以在应用程序中运行操作。使用DoEvents循环空闲?

    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;
        }
    }
    

    这里的逻辑是在Application.Idle事件中,在这里我们调用DoEvents,没有消息排队,所以我们不能重新输入代码。每一个tidbit都会被处理得足够快,因此它不应该显著地占用消息队列(或UI)。

    那么,这种方法有什么坏处或缺点吗?即,在空闲事件中调用DoEvents是否安全?我知道 C# 5 will have a feature to address this sort of situation ,但对于那些不使用C#5(目前我们大多数人都是C#5)的人来说,出于好奇,这是一个好的计划吗?或者,有没有一种更简单的方法可以在长时间运行的操作中处理消息而不诉诸多线程?

    请不要以为我认为这是一颗神奇的子弹。我知道它和 与任何异步方法相同的陷阱 是 知道有多线程解决方案。我在回避这些。为什么?因为多线程比较复杂。我不认为那不切实际。

    1 回复  |  直到 15 年前
        1
  •  1
  •   Pieter van Ginkel    15 年前

    你在这里做的事情看起来很像 Cooperative multitasking Task.Factory.StartNew() 以及真正让它变得简单的第三方物流库。

    我建议你不要这样做。