Форум программистов, компьютерный форум, киберфорум
Visual Basic .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
22 / 22 / 7
Регистрация: 26.05.2011
Сообщений: 256
.NET 4.x

Неточность компонента Timer

18.03.2017, 19:55. Показов 1815. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый вечер!
Вот прямо проблема за проблемой...
Есть вот такой вот код:

VB.NET
1
2
3
4
5
6
7
8
9
10
11
Public Class frmMain
    Dim TimeCounter As Single = 0
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Timer1.Enabled = True
    End Sub
 
    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        TimeCounter += Timer1.Interval
        Label2.Text = CStr(TimeCounter / 1000)
    End Sub
End Class
В таймере интервал стоит 100.

Однако при сравнении показаний label2 с показаниями часов windows, погрешность вылазит аж на 6 секунд (отстает)!!!
Это че ж, мать-перемать его, такое?
Сорри за мой скромный русский.

P. S.: Intel Core i7 2600 (4 ядра, гипертрединг на 8)
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
18.03.2017, 19:55
Ответы с готовыми решениями:

Как вычислить погрешность компонента Timer
Всем привет.Суть вопроса в название темы.Примерная погрешность 15ms,а как ее рассчитать? Написал такой код: Public Class Form1 ...

Отсутствует событие Elapsed компонента Timer
Прошу подсказать в таком вопросе. Пишу примеры из книги Лабор "Си Шарп Создание приложений для Windows" И там в разделе 31. Таймер...

Создание своего компонента на основе компонента Timer
нужно создать свой компонент какбы который наследует компонент Таймер нужно хотя бы добавить несколько свойств помогите с идеей !!!!...

19
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
18.03.2017, 20:03
Для чего вам точность? Она вам либо не нужна, либо вы что-то не так делаете. А Timer и не обязан точно работать.
0
22 / 22 / 7
Регистрация: 26.05.2011
Сообщений: 256
18.03.2017, 20:11  [ТС]
Someone007, не знаю что там должно или не должно, но я привык к тому что при работе с микроконтроллером нету ничего точнее, чем прерывание по таймеру. Хотелось верить, что здесь таймер - не одно только название!
Для чего - вопрос второстепенный, допустим, секундомер хочу сделать и тикать миллисекунды хочу. Но, как я вижу "из это роя не выйдет ....."
Может есть тогда действительно точные методы замеров времени?
0
Эксперт .NET
 Аватар для Rius
13127 / 7687 / 1676
Регистрация: 25.05.2015
Сообщений: 23,456
Записей в блоге: 14
18.03.2017, 20:41
Stass48, забудьте про МК, здесь совсем не так и это считается нормально.
Данный компонент таймера с таймерами МК имеет общего только лишь название и наличие callback'ов.

Лучше опишите задачу, в которой понадобилось точно время замерять.
2
4708 / 3661 / 857
Регистрация: 02.02.2013
Сообщений: 3,518
Записей в блоге: 2
18.03.2017, 20:44
Можно использовать:
System.Threading.Timer
System.Timers.Timer
System.Windows.Forms.Timer (Timer Control)
Последний наименее точный (по отзывам).
Еще есть System.Diagnostics.Stopwatch.
2
22 / 22 / 7
Регистрация: 26.05.2011
Сообщений: 256
18.03.2017, 21:25  [ТС]
Rius, ovva, Someone007,
вот наконец конструктивный диалог складывается
Мне нужно сделать кроссфейд между двумя песнями на Bass. Для этого хочу управлять громкостями этих песен, но кроме этого, хочу дать юзеру возможность выставить длительность кроссфейда. Кинулся мучать таймер. Выставил интервал 1 мс.. Сделал счетчик и смотрю, что уж больно он медленно считает.... Думаю, мол, наверное не успевает вычислять и что из-за этого накапливается очередь и т. п... Ладно, думаю дальше... поставлю ка 100 мс... За 100 уж точно должно успеть посчитать и очереди не будет... Кинулся проверять - да, погрешность действительно меньше! Но все равно отставать на 6 секунд за минуту реального времени это ж вообще капец...

Добавлено через 4 минуты
Так что же из этого всего посоветуете?
0
Эксперт .NET
 Аватар для Rius
13127 / 7687 / 1676
Регистрация: 25.05.2015
Сообщений: 23,456
Записей в блоге: 14
18.03.2017, 21:34
Вы аудио-редактор пишете? Или хотите воспроизвести одну песню за другой?
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
18.03.2017, 21:34
Что нибудь типа этого: https://www.codeproject.com/Ar... -Framework
1
22 / 22 / 7
Регистрация: 26.05.2011
Сообщений: 256
18.03.2017, 21:54  [ТС]
Rius, для аудиоредактора уж точно потребовалась бы высочайшая точность...
Но нет, это просто плеер и мне нужен плавный переход между треками.

Someone007, весьма интересное решение, по крайней мере на первый взгляд. Но нужно "пощупать"
0
Эксперт .NET
 Аватар для Rius
13127 / 7687 / 1676
Регистрация: 25.05.2015
Сообщений: 23,456
Записей в блоге: 14
18.03.2017, 21:56
Stass48, не знаю, как именно воспроизводится звук нынче. Но теоретически можно было бы считать оба файла в буфер, полностью или участками по мере необходимости, поменять громкость участков в буфере, и уже их воспроизводить.
0
22 / 22 / 7
Регистрация: 26.05.2011
Сообщений: 256
18.03.2017, 22:13  [ТС]
Rius, но ведь это займет ресурсы/время, что в моем случае недопустимо.
0
 Аватар для ViterAlex
8951 / 4863 / 1886
Регистрация: 11.02.2013
Сообщений: 10,246
18.03.2017, 22:13
Stass48, когда мне понадобились точные отсчёты времени (10-15 мс), то я нашёл реализацию таймера, который полностью меня устроил.
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
 
//Основа таймера взята с [url]http://stackoverflow.com/questions/24839105/high-resolution-timer-in-c-sharp[/url]
 
namespace Ipt.Timer
{
    public class MultimediaTimer : IDisposable
    {
        #region Свойства
 
        // Hold the timer callback to prevent garbage collection.
        private readonly NativeMethods.MultimediaTimerCallback _callback;
        private bool _disposed;
        private int _interval;
        private int _resolution;
        private uint _timerId;
 
        public int Interval
        {
            get
            {
                return _interval;
            }
            set
            {
                CheckDisposed();
 
                if (value < 0)
                    throw new ArgumentOutOfRangeException("value");
 
                _interval = value;
                if (Resolution > Interval)
                    Resolution = value;
                if(IsRunning)
                {
                    StopInternal();
                    Start();
                }
            }
        }
 
        // Note minimum resolution is 0, meaning highest possible resolution.
        private int Resolution
        {
            get
            {
                return _resolution;
            }
            set
            {
                CheckDisposed();
 
                if (value < 0)
                    throw new ArgumentOutOfRangeException("value");
 
                _resolution = value;
            }
        }
 
        public bool IsRunning
        {
            get
            {
                return _timerId != 0;
            }
        }
 
        #endregion
 
        public MultimediaTimer()
            :this(25)
        {
        }
 
        public MultimediaTimer(int interval)
        {
            _callback = TimerCallbackMethod;
            Resolution = 15;
            Interval = interval;
        }
 
        public void Dispose()
        {
            Dispose(true);
        }
 
        ~MultimediaTimer()
        {
            Dispose(false);
        }
 
        public event EventHandler Elapsed;
 
        private void CheckDisposed()
        {
            if (_disposed)
                throw new ObjectDisposedException("MultimediaTimer");
        }
 
        private void Dispose(bool disposing)
        {
            if (_disposed)
                return;
 
            _disposed = true;
            if (IsRunning)
            {
                StopInternal();
            }
 
            if (!disposing)
                return;
            Elapsed = null;
            GC.SuppressFinalize(this);
        }
 
        public void Start()
        {
            CheckDisposed();
 
            if (IsRunning)
                throw new InvalidOperationException("Timer is already running");
 
            // Event type = 0, one off event
            // Event type = 1, periodic event
            uint userCtx = 0;
            _timerId = NativeMethods.TimeSetEvent((uint) Interval, (uint) Resolution, _callback, ref userCtx, 1);
            if (_timerId != 0)
                return;
            int error = Marshal.GetLastWin32Error();
            throw new Win32Exception(error);
        }
 
        public void Stop()
        {
            CheckDisposed();
 
            if (!IsRunning)
                throw new InvalidOperationException("Timer has not been started");
 
            StopInternal();
        }
 
        private void StopInternal()
        {
            NativeMethods.TimeKillEvent(_timerId);
            _timerId = 0;
        }
 
        private void TimerCallbackMethod(uint id, uint msg, ref uint userCtx, uint rsv1, uint rsv2)
        {
            var handler = Elapsed;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }
    }
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System.Runtime.InteropServices;
 
namespace Ipt.Timer
{
    internal static class NativeMethods
    {
        internal delegate void MultimediaTimerCallback(uint id, uint msg, ref uint userCtx, uint rsv1, uint rsv2);
 
        [DllImport("winmm.dll", SetLastError = true, EntryPoint = "timeSetEvent")]
        internal static extern uint TimeSetEvent(uint msDelay, uint msResolution, MultimediaTimerCallback callback, ref uint userCtx, uint eventType);
 
        [DllImport("winmm.dll", SetLastError = true, EntryPoint = "timeKillEvent")]
        internal static extern void TimeKillEvent(uint uTimerId);
    }
}

Правда на c#, но можно упаковать в библиотеку и дёргать нужные методы и события. Событие у него одно: Elapsed. Возникает в отдельном потоке.
1
Эксперт .NET
 Аватар для Rius
13127 / 7687 / 1676
Регистрация: 25.05.2015
Сообщений: 23,456
Записей в блоге: 14
18.03.2017, 22:14
Stass48, может быть вовсе и не займёт. Да и в вашем случае как раз допустимо.
0
259 / 200 / 49
Регистрация: 18.12.2015
Сообщений: 416
18.03.2017, 22:27
Можно обойтись обычным sleep и завернуть в отдельный поток?
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Imports System.Threading
Public Class Form1
    Dim TimeCounter As Integer = 1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim Thread As New Thread(AddressOf OneProcess) : Thread.IsBackground = True
        Thread.Start()
    End Sub
    Private Sub OneProcess()
        Me.Invoke(Sub()
                      Label2.Text = "Ожидание синхронизации с системным таймером..."
                      Do Until DateTime.Now.Second = 0 : Label3.Text = DateTime.Now.Second
                          Application.DoEvents()
                      Loop
                      Do Until TimeCounter = 120
                          Thread.Sleep(1000)
                          Label2.Text = TimeCounter
                          Label3.Text = DateTime.Now.Second
                          TimeCounter += 1
                          Application.DoEvents()
                      Loop
                  End Sub)
    End Sub
End Class
0
Эксперт .NET
 Аватар для Rius
13127 / 7687 / 1676
Регистрация: 25.05.2015
Сообщений: 23,456
Записей в блоге: 14
18.03.2017, 22:43
Jungl, нельзя, это костыль, к тому же вообще не работающий.
Никогда так не пишите.

Добавлено через 14 минут
Jungl, собственно, одного наличия в коде методов DoEvents (Qt и .Net) или ProcessMessages (Delphi/BCB) достаточно, что выпилить код полностью, ибо это страшный костыль.

В вашем случае всё усугубляется тем, что якобы в потоке якобы выполняется метод OneProcess и код в нём. Только вот код этот на самом выполняется в цикле сообщений окна, что делает тот поток ненужным чуть более, чем полностью.

А ещё Thread.Sleep имеет малоизвестные особенности, могущие предоставить множество часов интереснейшей отладки.

Jungl, в .Net есть замечательные средства для работы с потоками. Изучайте их. Не плодите чудовищ.
2
259 / 200 / 49
Регистрация: 18.12.2015
Сообщений: 416
18.03.2017, 22:55
Простите, не по душе мне, когда таскаешь форму, а циферки стоят. Можно и через таймер со StopWatch'ем?
VB.NET
1
2
3
4
5
6
7
8
9
10
11
    Private stopWatch As New Stopwatch()
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        stopWatch.Start()
        Timer1.Enabled = True
    End Sub
    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        Label2.Text = stopWatch.Elapsed.Seconds
        Label3.Text = DateTime.Now.Second
        Application.DoEvents()
        If stopWatch.Elapsed.Seconds = 120 Then Timer1.Enabled = False : stopWatch.Stop()
    End Sub
Добавлено через 4 минуты
Rius, спасибо за критику, я ее всегда приветствую. Согласен про потоки, пока окончательно не разобрался в них. Учимся.
А что конкретно с DoEvents не так? Я право не могу пока понять смысл вашего предложения относительно DoEvents
0
Эксперт .NET
 Аватар для Rius
13127 / 7687 / 1676
Регистрация: 25.05.2015
Сообщений: 23,456
Записей в блоге: 14
18.03.2017, 23:04
Jungl,
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System;
using System.Windows.Forms;
 
namespace Jungl1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.timer1.Start();
        }
 
        private void timer1_Tick(object sender, EventArgs e)
        {
            this.label1.Text = DateTime.Now.ToString("HH:mm:ss.ffffff");
        }
    }
}
Форму таскаю, цифры обновляются, без проблем. Windows 10, .Net 4.5.

Цитата Сообщение от Jungl Посмотреть сообщение
А что конкретно с DoEvents не так? Я право не могу пока понять смысл вашего предложения относительно DoEvents
  1. Во всех случаях, где я видел до сих пор применение DoEvents, без него можно красиво обойтись;
  2. Метод делает возможной нелогичную последовательность действий, которую новички не предвидят. Например повторный вызов того же метода, в котором уже крутится DoEvents;
  3. Поэтому во всех этих случаях (т.е. всегда) DoEvents является костылём. Не потому, что метод плохой, а потому как его применяют - как костыль для подпирания незнания иных способов.
1
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
18.03.2017, 23:05
Цитата Сообщение от Jungl Посмотреть сообщение
А что конкретно с DoEvents не так?
Все с ним не так. И всегда можно обойтись без него.
0
259 / 200 / 49
Регистрация: 18.12.2015
Сообщений: 416
18.03.2017, 23:12
Rius, благодарю.
1. А если мне хочется обновить данные на контроле формы? Me.Refresh?
2. Взято на заметку.
3. Переход с VBA дает о себе знать.
Цитата Сообщение от Rius Посмотреть сообщение
Форму таскаю, цифры обновляются, без проблем. Windows 10, .Net 4.5.
Так и у меня с таймером цифры обновляются. Хотелось бы пример без компонента таймера, например на том же Stopwatch.
0
Эксперт .NET
 Аватар для Rius
13127 / 7687 / 1676
Регистрация: 25.05.2015
Сообщений: 23,456
Записей в блоге: 14
18.03.2017, 23:18
Неа, Me.Refresh тоже костыль Если данные предоставлены в окно правильным способом, а цикл сообщений окна не загружен всякой фигнёй, которой в нём совсем не место, то окно само обновится быстро.

Stopwatch выдаёт значение промежутка времени между Start и Stop, а не вызывает что-то периодически.
Тут простой пример выкладывал с обновлением GUI из потока.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
18.03.2017, 23:18
Помогаю со студенческими работами здесь

Использование компонента Timer
...доброго времени суток, уважаемые форумчане!.. Вопрос по использованию компонента &quot;Timer&quot;: существует ли у него какое-то...

Максимальный интервал компонента Timer
...доброго времени суток, уважаемые форумчане! Возник такой вопрос: какой максимальный интервал можно &quot;отмерять&quot; компонентом...

Обработчик события OnTimer компонента Timer
Помогите создать обработчик событий OnTimer компонента Timer, который отображает каждую секунду период времени, прошедший с указанного в...

Как сделать паузу 3 секунды у компонента Timer?
подскажите пожалуйста как сделать паузу в работе у компонента Timer в 3 секунды.

Свойство Stretch компонента Image тормозит Timer
Всем привет. Вообщем у меня такая проблема, На форме есть timer, который по нажатию кнопки начинает перемещать Label слева-направо. Фоном...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru