Вызов DoEvents в Application.Idle - PullRequest
       8

Вызов DoEvents в Application.Idle

1 голос
/ 07 ноября 2010

Я держусь подальше от 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 (который в настоящее время является большинством из нас), и вообще любопытство, это хороший план? Или есть более простая альтернатива обработке сообщений во время длительной операции без использования многопоточности?

Пожалуйста, не думайте, что я представляю это как волшебную пулю. Я знаю, что он имеет те же ловушки, что и любой асинхронный подход . Я знаю, что все еще нужно поддерживать его заявление в согласованном состоянии. И я осознаю, что существуют многопоточные решения. Я избегаю тех. Зачем? Потому что многопоточность сложнее. Я не думаю, что это нецелесообразно.

1 Ответ

1 голос
/ 07 ноября 2010

То, что вы здесь делаете, очень похоже на Совместную многозадачность .Это интересная идея, но я бы сказал, что вы должны действительно использовать многопоточность для чего-то подобного..NET имеет много вспомогательных систем, таких как Task.Factory.StartNew() и библиотеки TPL, которые действительно облегчают эту задачу.

Я бы посоветовал против этого.

Для ясности: у меня нетЯсная причина против этого.Как и во многих областях, касающихся программирования: если оно работает, оно работает.Однако вы смешиваете вещи, которые не следует смешивать друг с другом, в частности фоновые задачи и задачи пользовательского интерфейса.Я полагаю, что когда вы отделите фоновые задачи и начнете работать, запачкав руки многопоточностью, пулами потоков, фоновыми задачами и TPL, вы быстро увидите, что они работают и в долгосрочной перспективе облегчают жизнь.

...