Вызов doevents в Application.idle
-
29-09-2019 - |
Вопрос
Я держусь подальше от применения. Я давно предпочел выполнять фоновую работу в Application. Но, для длительных задач, приемлемо ли запускать операции в 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 в мероприятии на холостом ходу? Я знаю, что C# 5 будет иметь функцию для решения этой ситуации, но для тех из нас, кто не использует C# 5 (который является большинством из нас на данный момент) и из -за общего любопытства, это хороший план? Или есть более простая альтернатива обработке сообщений во время длительной операции, не прибегая к многопоточному чтению?
Пожалуйста, не думаю, что я представляю, что это волшебная пуля. Я знаю, что это идет с те же ловушки, что и любой асинхронный подход. Отказ Я знаю, что нужно все еще иметь возможность сохранить его применение в последовательном состоянии. И я являюсь осознавая, что существуют многопоточные решения. Я избегаю их. Почему? Потому что мультипоточное количество сложнее. Я не думаю, что это нецелесообразно.
Решение
То, что вы здесь делаете, очень похоже Кооперативная многозадачность. Отказ Это интересная идея, но я бы сказал, что вы действительно должны использовать мульти -потоки для чего -то подобного. .NE Task.Factory.StartNew()
И библиотеки TPL, которые действительно облегчают это.
Я бы посоветовал против этого.
Чтобы быть ясным, хотя: у меня нет четкой причины против этого. Как и во многих областях, касающихся программирования: если оно работает, это работает. Тем не менее, вы смешиваете вещи, которые не следует смешивать вместе, в частности, фоновые задачи и задачи пользовательского интерфейса. Я полагаю, что когда вы разделяете фоновые задачи и начинаете Go Fenthy Dinling с помощью многопоточных потоков, пулов потоков, фоновых задач и TPL, вы быстро увидите, что он работает и облегчает жизнь в долгосрочной перспективе.