Как я могу использовать CreateTimerQueueTimer для создания таймера высокого разрешения в C#?

FWIW это то, что вам нужно для пристани 8

<plugin>
 <groupId>org.mortbay.jetty</groupId>
 <artifactId>jetty-maven-plugin</artifactId>
 <version>8.1.7.v20120910</version>
 <configuration>       
   <webApp>
    <contextPath>/</contextPath>
  </webApp>
 </configuration>
</plugin>
7
задан Justin Tanner 18 June 2009 в 23:46
поделиться

2 ответа

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

). Параметр PVOID, который передается в функцию обратного вызова, должен быть зафиксирован в памяти, поскольку снова неуправляемая функция ожидает, что он не будет двигаться после возврата из функции. Net это закрепление происходит (эффективно) автоматически, но только на время жизни вызываемой функции. Таким образом, если вы используете ссылку на некоторый управляемый объект (скажем, путем получения IntPtr к нему), базовый объект должен быть закреплен (опять же, GCHandle может использоваться для этого несколько другим способом). Чтобы увидеть, является ли это проблемой, попробуйте использовать IntPtr.Zero в качестве параметра, чтобы проверить, работает ли он.

Если это решает проблему, вам нужно будет либо выделить свой параметр как необработанные байты в неуправляемой куче (и соответственно маршалировать), используйте некоторый непреобразуемый тип, который можно безопасно поместить во что-то размером PVOID (например, Int32) или использовать метод GCHandle, описанный выше, для поддержания стабильного указателя на управляемый экземпляр, это будет иметь значительные последствия для производительности, если сделано неправильно.

Таким образом, если вы используете ссылку на некоторый управляемый объект (скажем, путем получения IntPtr к нему), базовый объект должен быть закреплен (опять же, GCHandle может использоваться для этого несколько другим способом). Чтобы увидеть, является ли это проблемой, попробуйте использовать IntPtr.Zero в качестве параметра, чтобы проверить, работает ли он.

Если это решает проблему, вам нужно будет либо выделить свой параметр как необработанные байты в неуправляемой куче (и соответственно маршалировать), используйте некоторый непреобразуемый тип, который можно безопасно поместить во что-то размером PVOID (например, Int32) или использовать метод GCHandle, описанный выше, для поддержания стабильного указателя на управляемый экземпляр, это будет иметь значительные последствия для производительности, если сделано неправильно.

Таким образом, если вы используете ссылку на некоторый управляемый объект (скажем, путем получения IntPtr к нему), базовый объект должен быть закреплен (опять же, GCHandle может использоваться для этого несколько другим способом). Чтобы увидеть, является ли это проблемой, попробуйте использовать IntPtr.Zero в качестве параметра, чтобы проверить, работает ли он.

Если это решает проблему, вам нужно будет либо выделить свой параметр как необработанные байты в неуправляемой куче (и соответственно маршалировать), используйте некоторый непреобразуемый тип, который можно безопасно поместить во что-то размером PVOID (например, Int32) или использовать метод GCHandle, описанный выше, для поддержания стабильного указателя на управляемый экземпляр, это будет иметь значительные последствия для производительности, если сделано неправильно.

3
ответ дан 6 December 2019 в 15:29
поделиться

Вот ссылка на оболочку C # для CreateTimerQueueTimer :

http://social.msdn.microsoft.com/Forums/en-CA/csharpgeneral/thread/822aed2d-dca0-4a8e -8130-20fab69557d2

(прокрутите вниз до последнего сообщения Hobz для примера класса)

Я только что попробовал это сам, и он отлично работает. Однако вам нужно будет добавить вызов timeBeginPeriod (1) перед запуском таймера, чтобы настроить вашу систему на высокое разрешение. timeSetEvent вызывает timeBeginPeriod внутри, поэтому некоторые ошибочно полагают, что он создает таймер с более высоким разрешением.

9
ответ дан 6 December 2019 в 15:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: