Как долго длится задержка между Control.Invoke() и вызовом его делегата?

У меня есть механизм кода, который воспроизводит длинные файлы 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 ответ

Решение

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

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

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

Другие вопросы по тегам