我远离 Application.DoEvents,因为存在重新进入的问题,并且总是有另一种方法可以避免阻止 UI。我一直喜欢在 Application.Idle 事件中做后台工作,作为多线程的简单替代方案。但是,对于长时间运行的任务,是否可以在 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;
}
}
这里的逻辑是,在我们调用 DoEvents 的 Application.Idle 事件中,没有消息排队,因此我们应该无法重新输入代码。每个花絮都会被足够快地处理,以至于它不应该显着阻塞消息队列(或 UI)。
那么,这种方法有什么害处或缺点吗?即,在 Idle 事件中调用 DoEvents 是否安全?我确实知道C# 5 将有一个功能来解决这种情况,但是对于我们这些不使用 C# 5 的人(目前我们大多数人),出于普遍的好奇,这是一个好的计划?或者是否有更简单的替代方法来在长时间运行的操作期间处理消息而不诉诸多线程?
请不要以为我认为这是一颗灵丹妙药。我知道它带有与任何异步方法相同的缺陷。我知道一个人必须仍然能够保持他的应用程序处于一致状态。而且我知道有多线程解决方案。我正在避免那些。为什么?因为多线程比较复杂。我不认为这是不切实际的。