Я держусь подальше от Application.DoEvents, поскольку существует проблема повторного входа и всегда есть другой способ избежать удержания пользовательского интерфейса. Я давно предпочитал выполнять фоновую работу в событии 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;
}
}
Логика здесь заключается в том, что в событии Application.Idle, где мы вызываем DoEvents, нет сообщений в очереди, поэтому мы не сможем повторно ввести код. Каждый кусок будет обработан достаточно быстро, чтобы он не занимал очередь сообщений (или пользовательский интерфейс) значительно.
Итак, есть ли вред или недостаток в этом подходе? А именно, безопасно ли вызывать DoEvents в событии Idle? Я знаю, что C # 5 будет иметь функцию для решения такой ситуации , но для тех из нас, кто не использует C # 5 (который в настоящее время является большинством из нас), и вообще любопытство, это хороший план? Или есть более простая альтернатива обработке сообщений во время длительной операции без использования многопоточности?
Пожалуйста, не думайте, что я представляю это как волшебную пулю. Я знаю, что он имеет те же ловушки, что и любой асинхронный подход . Я знаю, что все еще нужно поддерживать его заявление в согласованном состоянии. И я осознаю, что существуют многопоточные решения. Я избегаю тех. Зачем? Потому что многопоточность сложнее. Я не думаю, что это нецелесообразно.