【C# WinForms】System.Windows.Forms.Timerとマルチメディアタイマの精度を比較してみる

タイマの精度測定

System.Windows.Forms.Timerとマルチメディアタイマの精度を比較してみました。

測り方は各タイマのイベント発生を100ms毎に設定しシリアルポートにデータ送信させ、オシロスコープでシリアルポートの送信間隔を確認します。

タイマイベント発生間隔(データ送信間隔)のばらつきを確認するためオシロスコープは取得した波形を重ね書きするモードにしておきます。

System.Windows.Forms.Timerの精度

コード

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        private System.Windows.Forms.Timer timer1;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            serialPort1.BaudRate = 9600;
            serialPort1.Parity = Parity.None;
            serialPort1.DataBits = 8;
            serialPort1.StopBits = StopBits.One;
            serialPort1.Handshake = Handshake.None;
            serialPort1.PortName = "COM3";
            serialPort1.Open();

            timer1 = new System.Windows.Forms.Timer();
            timer1.Tick += new System.EventHandler(timer1_Tick);
            timer1.Interval = 100;
            timer1.Start();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            byte[] sendData = { 0xff };
            serialPort1.Write(sendData,0,sendData.Length);
        }
    }
}

結果

設定値の100msに対して-4ms~+24msでした。頻度的にも+側のずれの方が多そうでした。

マルチメディアタイマの精度

コード

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    public partial class Form1 : Form
    {
        [DllImport("winmm.dll", SetLastError = true)]
        static extern UInt32 timeSetEvent(UInt32 uDelay, UInt32 uResolution, LPTIMECALLBACK lpTimeProc, UInt32 dwUser, UInt32 fuEvent);

        [DllImport("winmm.dll", SetLastError = true)]
        static extern UInt32 timeKillEvent(UInt32 uTimerID);

        private delegate void LPTIMECALLBACK(UInt32 uTimerID, UInt32 uMsg, UInt32 dwUser, UInt32 dw1, UInt32 dw2);

        private UInt32 timer_id;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            serialPort1.BaudRate = 9600;
            serialPort1.Parity = Parity.None;
            serialPort1.DataBits = 8;
            serialPort1.StopBits = StopBits.One;
            serialPort1.Handshake = Handshake.None;
            serialPort1.PortName = "COM3";
            serialPort1.Open();

            timer_id = timeSetEvent(100, 1, Timer_Callback, 0, 1);
            //周期100ms,分解能1ms,繰り返しイベント発生
        }

        ~Form1()
        {
            timeKillEvent(timer_id);
        }

        private void Timer_Callback(UInt32 uTimerID, UInt32 uMsg, UInt32 dwUser, UInt32 dw1, UInt32 dw2)
        {
            byte[] sendData = { 0xff };
            serialPort1.Write(sendData, 0, sendData.Length);
        }
    }
}

結果

設定値の100msに対して-1ms~+1msでした。

コメント

タイトルとURLをコピーしました