2010-03-17 1 views
1

Я настраиваю таймер для вызова события в моем приложении. Проблема заключается в том, что выполнение события искажается другими операциями Windows. Ex. открытие и окно, загрузка веб-страницы. Мне нужно, чтобы мероприятие проводилось точно вовремя, каждый раз.Необходимые события для выполнения событий таймера, точность метронома

Когда я впервые установил приложение, использовал звуковой файл, как метроном, чтобы прослушивать даже стрельбу, в устойчивом состоянии, его стрельба вправо, но как только что-то происходит в среде Windows, звук срабатывает медленнее, потом немного соскользнуть, чтобы догнать.

Итак, я добавил метод ведения журнала для события, чтобы установить таймер. Из этих данных кажется, что приложение-приложение не влияет на таймер, но на меня влияют мои вызовы приложений. Я понял это, проверив datetime.now в этом случае, и если я установил его в 250 миллисекунд, что составляет 4 клика в секунду. Вы получаете данные, как показано ниже.

(сек) :(мс)

1: 000 1: 250 1: 500 1: 750

2: 000 2: 250 2: 500 2: 750

3: 000 3: 250 3: 500 3: 750

(позволяет сказать, что я выполнить некоторые окна событий) (время будет искажать)

4: 122 4: 388 4: 600 4: 876

(прекратить делать то, что я делал в окнах) (собирается сократить данные simplicit, мой список был 30сек долго)

5: 124 5: 268 5: 500 5: 750

(вы бы себе время вернуться назад те же миллисекунды это было в начале)

6: 000 6: 250 6: 500 6: 750

7: 000 7: 250 7: 500 7: 750

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

Есть ли что-нибудь, что я могу сделать в .NET, надеясь использовать приложение XAML/WPF, thats исправит перекос событий?

thx.

+0

Что-то, что я вижу после прочтения этого еще раз: каким образом вы пишете в журнал? Если вы сделаете это с доступом к файлу с промывкой, запись на диск может быть в миллисекундах. Поэтому вы должны действительно регистрироваться только в памяти. – mnemosyn

ответ

2

Выполнение этого права может быть очень, очень сложно, если возможно вообще. Некоторым приложениям обработки звука действительно тяжело это делать. Стандартные настройки компьютера не предназначены для такого режима работы в реальном времени, потому что вы не можете контролировать, сколько потоков/процессов будет выполняться в фоновом режиме.

Однако, как первая попытка , вы можете использовать цикл вместо асинхронного триггера. Обратите внимание, что это может сильно повлиять на процессор и по-прежнему не гарантирует точное время. Псевдо-код:

forever 
{ 
    // This will bring your precision down to the level of thread 
    // timing precision 
    Sleep(0); 

    LastTime = GetPerformanceTimer(); 
    if(LastTime > NextInterval) 
    { 
     // Play sound, update last time 
    } 
} 

где GetPerformanceTimer является своего рода метод, основанный QueryPerformanceCounter. Я написал очень простой профайлер после http://www.emphess.net/2009/03/04/a-very-simple-profiler/, но код там очень прост и в основном дает вам время в секундах с момента начала таймера с очень высокой точностью.

Возможно, вы также захотите присвоить процессу более высокий приоритет, чтобы другие процессы не остановили ваш процесс.

+0

Что можно сказать о услугах мультимедийного таймера Win32? Есть ли хороший пример того, как установить приложение на более высокий приоритет? –

+0

Прежде всего, вы можете точно настроить точность 'timeGetTime', используя' timeBeginPeriod'. Обратите внимание, что стандартная точность таймера мультимедиа Windows ужасна (около 10 мс!), Тогда как QPF находится в микросекундах. См. Эту ссылку в MSDN http://msdn.microsoft.com/en-us/library/dd757629(VS.85).aspx. Тем не менее, я никогда не использовал это раньше. Думая снова, я бы не возился с приоритетом потоков. – mnemosyn

+0

Может ли проблема также воспроизводиться в WAV-файле по сравнению с MIDI-звуком? Или просто так, как я играю в WAV-файл? Поверьте, я использовал System.Media.SoundPlayer. Дон, у меня есть код передо мной. Это был таймер мультимедиа, который я пробовал, http://www.codeproject.com/KB/miscctrl/lescsmultimediatimer.aspx –

1

Я ожидаю, что таймер будет стрелять довольно близко к точно по времени, как вы заметили. Тем не менее, даже если это связано с обработкой процессора, это может повлиять.

Похоже, что вы хотите, чтобы события происходили в вашей строке пользовательского интерфейса точно вовремя, и это будет проблемой. Код, который обновляет пользовательский интерфейс, должен выполняться в потоке пользовательского интерфейса. Если что-то еще происходит в потоке пользовательского интерфейса при срабатывании таймера, операция обновления с таймера должна ждать.

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

Если вам не нужно обновлять пользовательский интерфейс, вы можете получить чуть более согласованный ответ, используя System.Threading.Timer с методом обратного вызова, чем с использованием одного из таймеров, использующих события. Тем не менее, я был бы очень удивлен, если бы вы могли использовать любой метод на основе таймера для надежной работы в этом приложении.

Смежные вопросы