사소한 아이의 소소한 스킬/C#

C#에서 초마다 정확하게 수행하는 타이머??!!

주지님 2024. 4. 5. 14:23
반응형

우리가 개발을 하다보면 멀티 스레드환경으로 꼭 개발이 들어가게 된다.

 

특히나 UI를 만지다 보면 필수...

 

WPF에서는 특히나 Single Thread 환경이기에 UI Thread에 대한 처리가 꼭 필요하다.

 

MVVM으로 처리를 한다면 백그라운드에서 알아서 잘 해주기에 많은 신경은 안써주어도 알아서 바인딩되서 착착 UI에 업데이트되지만?

 

아무튼.

 

이러한 상황에서 1초마다 Timer를 발생시키는 System.Timer 요녀석을 통해 매 초 특정 기능을 수행하려고 한다.

 

허나 System.Timer는 오차가 존재한다는 점.

 

윈도우 응용프로그램은 하드웨어 클락? 을 이용치 않기에 오차가 무조건 존재하고 나는 그 오차가 +-0.000몇초차이로 존재하며 앞뒤로 있을 것이라 생각했지만 왠걸...

 

 

 

요런식으로 쌓이기만한다....

 

이거는 생각못했는데 말이지.......

 

아무튼 이러한 문제가 있기에 몇시간을 켜두거나 며칠을 켜두게 되면 특정 초는 수행이 되지 않는 문제가 발생할 것이다!!!

 

그렇다면 이러한 문제 해결은 어찌 해야 하는가...

 

답은

 

 

Multimedia Timer

 

멀티미디어 타이머라는것이 존재한다.

 

 

NuGet에서는 .NET Core를 위해서 해당 기능이 있다곤 하지만, 해당 기능을 가지고 확장한 .NET Framework 용도 있다.

 

아무튼 그래서 나는 찾은게 

 

PrecisionTimer

 

 

친히 Nuget에 존재한다.

 

그냥 받고서 적용시켜서 실행하면 끝..

 

실행 코드 간단히 말하면

 

using System;
using System.Windows;
using System.Threading;
using System.Runtime.InteropServices;

using PrecisionTiming;


namespace WpfApp1
{
    /// <summary>
    /// MainWindow.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class MainWindow : Window
    {

        public static PrecisionTimer MyTimer = new PrecisionTimer();

        // 윈도우 응용프로그램이기에 Console창을 띄워주기 위해 만들었다.
        static class NativeMethods
        {
            [DllImport("kernel32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool AllocConsole();
        }

        public MainWindow()
        {
            InitializeComponent();

            // Console창 만들기
            NativeMethods.AllocConsole();

            MyTimer.SetInterval(Test, 1000);
            MyTimer.Start(1000);

        }

        public void Test()
        {
            Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff"));

            Random RR = new Random();

            // 임의로 Sleep 걸어서 수행시간 늘리기
            Thread.Sleep(RR.Next(0, 500));
        }
    }
}

 

응용프로그램 켜지자 마자 timer 생성하고 1초마다 잘 찍히는지 Console찍고.

 

혹여나 처리 시간이 길어져도 해당 시간을 유지하는지 체크하기 위해서 Sleep구문도 랜덤으로 작성.

 

해당 기능으로 구현해서 확인해보면

 

 

System.Timer와는 다르게 잘 유지되는것을 알 수 있다.

 

만약 초마다 정확하게 1번씩 실행되는 타이머등을 이용하고 싶다면 MultimediaTimer를 사용하자!!

반응형