using System;
using System.Threading;
using System.Windows.Forms;

namespace SleepCheck
{
    // C#.NETのThread.Sleep()処理は多少誤差があるようなので、
    // 動作を確認するため作成した実験プログラムです。
    public partial class Form1 : Form
    {
        int sleepTime;
        int loopNum;

        public Form1()
        {
            InitializeComponent();
        }

        private void buttonRun_Click(object sender, EventArgs e)
        {
            sleepTime = Convert.ToInt32(numericUpDownSleep.Value);
            loopNum = Convert.ToInt32(numericUpDownLoop.Value);

            Thread thread = new Thread(new ThreadStart(this.DoWork));
            thread.IsBackground = true;
            thread.Start();
        }

        private delegate void ClearMsgDelegate();
        private void ClearMsg()
        {
            if (InvokeRequired)
            {
                // 別スレッドから呼び出された場合
                Invoke(new ClearMsgDelegate(ClearMsg));
                return;
            }

            textBoxMsg.Text = string.Empty;
        }

        private delegate void AddMsgDelegate(string msg);
        private void AddMsg(string msg)
        {
            if (InvokeRequired)
            {
                // 別スレッドから呼び出された場合
                Invoke(new AddMsgDelegate(AddMsg), new Object[] { msg });
                return;
            }

            textBoxMsg.Text += msg + "\r\n";
            textBoxMsg.Select(textBoxMsg.Text.Length, 0);
            textBoxMsg.ScrollToCaret();
        }

        private void DoWork()
        {
            ClearMsg();

            DateTime minDiff = DateTime.MaxValue;
            DateTime maxDiff = DateTime.MinValue;
            for (int i = 0; i < loopNum; i++)
            {
                DateTime start = DateTime.Now;
                AddMsg("Start: " + start.ToString("yyyy/MM/dd HH:mm:ss.fff"));
                //AddMsg("Start: " + start.ToString("yyyy/MM/dd HH:mm:ss.fff") + ", " + start.Ticks);

                Thread.Sleep(sleepTime);

                DateTime stop = DateTime.Now;
                AddMsg("Stop: " + stop.ToString("yyyy/MM/dd HH:mm:ss.fff"));
                //AddMsg("Stop: " + stop.ToString("yyyy/MM/dd HH:mm:ss.fff") + ", " + stop.Ticks);

                DateTime diff = new DateTime(stop.ToBinary() - start.ToBinary());
                AddMsg("Diff: " + diff.ToString("HH:mm:ss.fff"));

                if (diff.CompareTo(minDiff) < 0)
                {
                    minDiff = new DateTime(diff.ToBinary());
                }
                if (diff.CompareTo(maxDiff) > 0)
                {
                    maxDiff = new DateTime(diff.ToBinary());
                }
            }

            AddMsg("Min diff: " + minDiff.ToString("HH:mm:ss.fff"));
            AddMsg("Max diff: " + maxDiff.ToString("HH:mm:ss.fff"));
        }
    }
}