Проблема с быстродействием таймера WPF

#c# #wpf #timer

#c# #wpf #таймер

Вопрос:

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

  repeatTimer_Tick(this, new EventArgs());
        repeatLeftTimer.Interval = TimeSpan.FromMilliseconds(1);
        repeatLeftTimer.Tick  = new EventHandler(repeatTimer_Tick);
  

Комментарии:

1. Это WPF или ASP.NET ? Эти технологии не работают вместе, нет смысла включать оба тега…

Ответ №1:

Таймеры в Windows имеют разрешение в несколько миллисекунд, IIRC, что составляет от 10 до 50 мс. Вы не можете заставить обычный таймер отсчитывать каждую миллисекунду.

Комментарии:

1. есть ли какое-либо решение для этого?

2. Я думаю, что разрешение таймера в лучшем случае составляет 13 мс. Что составляет ~ 75 кадров в секунду. Вам действительно нужно больше 75 кадров в секунду в вашей анимации? Если вы должны анимировать с использованием таймера, то вычислите значение разности между предыдущим кадром и анимацией с использованием разности.

3. Я думаю, что самый простой способ — использовать BackgroundWorker , прокручивать свой список в ProgressChanged обработчике событий и вызывать yourWorker.ReprotProgress в цикле с Sleep(1000) промежуточными элементами…

4. @DanielHilgarth хорошая идея … Я обнаружил, что вызов Sleep (1) хорош — он в основном освобождает минимальное количество времени для других потоков / процессов и предотвращает загрузку фонового рабочего цикла 100% процессора. На каждой итерации цикла вы просто получаете текущее время, но делаете что-то только всякий раз, когда (текущее время — в последний раз) >= timer_period.

Ответ №2:

Я бы попытался использовать анимацию для того, что вы делаете.

Классы таймеров .NET обычно имеют минимальный интервал в 15,6 мс. Если вам нужно более быстрое увеличение (до 1 мс), Windows предоставляет мультимедийный таймер в неуправляемом API. Вы могли бы импортировать этот таймер и использовать его — я это сделал, и это работает.

Я основал свой код на этом:http://www.codeproject.com/KB/miscctrl/lescsmultimediatimer.aspx

Должно быть больше всего того, что вам нужно; Я добавил некоторый код, чтобы посмотреть на таймер высокого разрешения и наблюдать за временем между тактами — я смог довести его до 1 мс, = 0,10 мс

Ответ №3:

У вас есть два хороших и (относительно) простых варианта:

  1. Используйте анимацию — WPF имеет очень универсальную систему анимации, которая, вероятно, сможет сделать то, что вам нужно.

  2. Используйте CompositionTarget.События рендеринга вызываются как можно быстрее (каждый кадр), и вы несете ответственность за установку текущего статуса в каждом вызове на основе текущего времени (именно так работают встроенные анимации)

Комментарии:

1. у меня есть окно списка с более чем 1000 записями. я упорядочил записи по 5 строк в каждом столбце. Я хочу переместить каждый столбец по горизонтали

2. @Geetha — хорошо, у вас все еще есть эти два варианта, вы можете использовать DoubleAnimation для прокрутки столбцов или вы можете использовать CompositionTarget. Рендеринг и немного математики — это система, созданная для поддержки плавной анимации в WPF

Ответ №4:

Если вам нужно высокое разрешение, я бы посоветовал заглянуть в класс Stopwatch. Используйте поле Frequency и свойство ElapsedTicks, чтобы получить требуемое разрешение. Однако обратите внимание, что разрешение секундомера будет меняться в зависимости от аппаратного обеспечения. Прочитайте ссылку на документацию msdn для получения дополнительной информации.