반응형
현재 타이머의 간격인 1ms와 출력창의 현재 시간과 옆의 간격 1ms
(1ms 이상의 간격으로 이벤트를 발생시키고 싶을때 사용하시면 좋습니다)
필요한 파라미터로는 Interval 과 Resolution이 있습니다.
Interval 은 최소 1ms로 타이머의 간격을 설정할 수 있고 Resolution은 작은값일수록 해상도가 높으며 0일때 최대의 해상도 입니다.
시스템의 부하를 줄이기 위해 Resolution을 최대한 큰값을 사용하라고 하네요.
내부적으로는 인터벌 설정시에 레졸루션이 더 크면 해당 인터벌의 값으로 레졸루션을 설정하게 되어 있습니다.
(인터벌만 설정해 주시면 될거 같네요)
멀티미디어 클래스
public class MultimediaTimer : IDisposable
{
private bool disposed = false;
private int interval, resolution;
private UInt32 timerId;
// Hold the timer callback to prevent garbage collection.
private readonly MultimediaTimerCallback Callback;
public MultimediaTimer()
{
Callback = new MultimediaTimerCallback(TimerCallbackMethod);
Resolution = 5;
Interval = 10;
}
~MultimediaTimer()
{
Dispose(false);
}
public int Interval
{
get
{
return interval;
}
set
{
CheckDisposed();
if (value < 0)
throw new ArgumentOutOfRangeException("value");
interval = value;
if (Resolution > Interval)
Resolution = value;
}
}
// Note minimum resolution is 0, meaning highest possible resolution.
public int Resolution
{
get
{
return resolution;
}
set
{
CheckDisposed();
if (value < 0)
throw new ArgumentOutOfRangeException("value");
resolution = value;
}
}
public bool IsRunning
{
get { return timerId != 0; }
}
public void Start()
{
CheckDisposed();
if (IsRunning)
throw new InvalidOperationException("Timer is already running");
// Event type = 0, one off event
// Event type = 1, periodic event
UInt32 userCtx = 0;
timerId = NativeMethods.TimeSetEvent((uint)Interval, (uint)Resolution, Callback, ref userCtx, 1);
if (timerId == 0)
{
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;
}
public event EventHandler Elapsed;
public void Dispose()
{
Dispose(true);
}
private void TimerCallbackMethod(uint id, uint msg, ref uint userCtx, uint rsv1, uint rsv2)
{
var handler = Elapsed;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
private void CheckDisposed()
{
if (disposed)
throw new ObjectDisposedException("MultimediaTimer");
}
private void Dispose(bool disposing)
{
if (disposed)
return;
disposed = true;
if (IsRunning)
{
StopInternal();
}
if (disposing)
{
Elapsed = null;
GC.SuppressFinalize(this);
}
}
}
internal delegate void MultimediaTimerCallback(UInt32 id, UInt32 msg, ref UInt32 userCtx, UInt32 rsv1, UInt32 rsv2);
internal static class NativeMethods
{
[DllImport("winmm.dll", SetLastError = true, EntryPoint = "timeSetEvent")]
internal static extern UInt32 TimeSetEvent(UInt32 msDelay, UInt32 msResolution, MultimediaTimerCallback callback, ref UInt32 userCtx, UInt32 eventType);
[DllImport("winmm.dll", SetLastError = true, EntryPoint = "timeKillEvent")]
internal static extern void TimeKillEvent(UInt32 uTimerId);
}
사용
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace WindowsFormsApp9
{
public partial class Form1 : Form
{
Stopwatch sw = new Stopwatch();
static MultimediaTimer timer ;
public Form1()
{
InitializeComponent();
timer = new MultimediaTimer() { Interval = 1, Resolution = 0};
timer.Elapsed += Handler;
timer.Start();
sw.Start();
}
double dNow ,dPre;
public void Handler(object sender, EventArgs e)
{
dNow = sw.ElapsedMilliseconds - dPre ;
Console.WriteLine($"MultimediaTimer Timer elapsed {DateTime.UtcNow:o} {dNow}");
dPre = sw.ElapsedMilliseconds ;
}
private void timer1_Tick(object sender, EventArgs e)
{
label2.Text = dNow.ToString();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
timer.Stop();
}
}
}
사용한 소스파일
반응형
'C#' 카테고리의 다른 글
[NSIS] 프로그램 실행중일때는 확인 메시지후 종료하기 (0) | 2022.01.19 |
---|---|
[Azure DevOps] 작업영역 강제 제거하기 (0) | 2022.01.19 |
C# delegate 실 사용 예제 !!! (쓰레드에서 접근하는 UI 예제 포함) (0) | 2021.12.23 |
C# 배열 초기화, 구조체 초기화 (0) | 2021.12.16 |
C# OpenFileDialog (파일 불러오기, 파일 열기) (0) | 2021.07.12 |