Как долго длится задержка между Control.Invoke () и вызовом его делегата? - PullRequest
6 голосов
/ 21 февраля 2010

У меня есть механизм кодирования, который воспроизводит длинные файлы WAV, последовательно воспроизводя меньшие фрагменты с помощью методов API waveOutOpen и waveOutWrite. Чтобы обновить мой пользовательский интерфейс во время воспроизведения файла, из функции обратного вызова, когда каждый буфер завершает воспроизведение, я вызываю отдельный поток (потому что вы хотите сделать как можно меньше внутри функции обратного вызова), который вызывает метод в моей форме.

Форма содержит уровень класса EventHandler, который обрабатывает метод, в рамках которого я обновляю элементы интерфейса с новой информацией. В методе формы, вызываемом из функции обратного вызова waveOutWrite, я использую метод Invoke следующим образом:

if (_updatedisplay == null)
{
    // UpdateDisplay contains code to set control properties on the form
    _updatedisplay = new EventHandler(UpdateDisplay);
}
Invoke(_updatedisplay);

Все работает, но, похоже, время от времени происходит заметная задержка или задержка обновления элементов пользовательского интерфейса. Это легко увидеть, потому что я использую метод UpdateDisplay для управления анимацией, поэтому задержки выглядят как «икота», когда спрайт останавливается на долю секунды, прежде чем он переходит на ожидаемую позицию.

Возможно ли, что иногда при межпотоковом обмене данными возникает большая (может быть, 10-15 миллисекунд) задержка? Если так, то как лучше справиться с чем-то вроде этого?

Обновление : кстати, я определенно не уверен, что Invoke является виновником здесь. Другой возможностью является задержка между моментом окончания воспроизведения фрагмента звука и фактическим вызовом функции обратного вызова.

Обновление 2 : согласно предложению itowlson, я использовал System.Diagnostics.Stopwatch для сравнения лага между Invoke и вызовом метода. Из 1156 измерений я получил 1146 при 0 мс, 8 при 1 мс и 2 при 2 мс. Я думаю, можно с уверенностью сказать, что Invoke здесь не мой виновник.

1 Ответ

3 голосов
/ 21 февраля 2010

Да, может быть произвольно большая задержка. Invoke работает, отправляя сообщение Windows целевому элементу управления, поэтому он будет обрабатываться только тогда, когда целевой поток качает сообщения. Если поток уже обрабатывает сообщение, и эта обработка занимает время, то может возникнуть значительная задержка, прежде чем поток прокачает свое следующее сообщение и тем самым обработает Invoke.

Лучшим способом может быть вызов BeginInvoke. Это не предотвращает потенциальную задержку в потоке пользовательского интерфейса, обрабатывающего сообщение, но спасает ваш вызывающий поток от блокировки, пока он ожидает передачи сообщений. Тем не менее, это может не помочь в вашем сценарии, где это звучит так, как будто занятость потока пользовательского интерфейса вызывает сбои в анимации.

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

...