C#

C#] PeriodicTimer class

Fastlane 2024. 1. 9. 13:19
728x90
반응형

몇 시스템 개발 시, task 실행을 일정한 시간을 두고 해야할 때가 있다. C#은 .NET 6에서 소개된 PeriodicTimer class를 제공한다. 

 

기능과 사용법을 살펴보고 간단히 구현해보자. 

 

C#에서 PeriodicTimer Class 작동법

1. 필요한 변수를 정의하자. 

private readonly PeriodicTimer _periodicTimer;
private readonly CancellationTokenSource _cancellationToken = new();
private Task? _task;
private int _size;

차후 초기화할 PeriodicTimer 변수가 있다. 반복 Task를 종료시킬때 사용할 CancellationTokenSource 변수를 정의하고 초기화했다. random number의 배열을 생성하고 _size 변수가 elements의 수를 갖는다. 

 

2. _periodicTimer, _size를 초기화할 constructor를 만든다. 

public PeriodicTimerMethods(TimeSpan timeSpan, int size) 
{
    _periodicTimer = new PeriodicTimer(timeSpan);
    _size = size;
}

 

3. 우리가 원하는 시간에 random array를 생성하는 task를 실행하는 함수를 만든다. 

public static int[] CreateRandomArray(int size)
{
    var array = new int[size];

    for (int i = 0; i < size; i++)
    {
        array[i] = Random.Shared.Next();
    }
    
    return array;
}

 

이 함수는 주어진 size의 random 숫자 배열을 반환한다. 

 

4. CreateRandomArray()함수를 호출하고 PeriodicTimer를 초기화하는 함수를 구현한다. 

private async Task RandomArrayTimerAsync() 
{
    try 
    {
        var stopWatch = System.Diagnostics.Stopwatch.StartNew();
        var numberOfArrays = 1;

        while (await _periodicTimer.WaitForNextTickAsync(_cancellationToken.Token)) 
        {
            var array = CreateRandomArray(_size);

            foreach (var item in array)
            {
                Console.WriteLine(item);
            }

            Console.WriteLine($"Created {numberOfArrays++} arrays in {stopWatch.Elapsed.Seconds}s");
            Console.WriteLine(DateTime.Now.ToString("O"));
        }
    }
    catch(OperationCanceledException) 
    {
    }
}

WaitForNextTickAsync() 함수는 timer의 next tick이나 종료시까지 대기한다. 함수 실행 시, 몇 초가 소요되는지 print하기 위해 Stopwatch instance도 생성했다. 

 

5. task의 초기화 종료를 위한 helper methods를 생성한다. 

public void Start() 
{
    _task = RandomArrayTimerAsync();
}

public async Task StopTaskAsync() 
{
    if (_task is null) 
    {
        return;
    }

    _cancellationToken.Cancel();
    await _task;
    _cancellationToken.Dispose();
    Console.WriteLine("The array task was canceled");
}

StopTaskAsync() 함수에서 IsCancellationRequested property를 true로 set 하는 Cancel() 함수를 호출한다. resources를 해제하도록 object를 dispose하기 전에 task를 마무리하도록 밀린작업실행을 허용한다. 

 

6. main program에서 적상동작을 확인하자. 

Console.WriteLine("Enter array size");
var numOfElements = Convert.ToInt32(Console.ReadLine());

var timerTask = new PeriodicTimerMethods(TimeSpan.FromSeconds(1), numOfElements);
timerTask.Start();

Console.WriteLine("Press any button to terminate the task");
Console.ReadKey();

await timerTask.StopTaskAsync();

 

 

output을 보면 1초 간격으로 random arrays가 3개씩 발생하는 것을 볼 수 있다. 

 

위 버전은 Program.Main style이고 아래는 top-level statement 이다. 

둘다 동일하게 동작한다. 

 

왜 PeriodicTimer를 사용해야 하는가?

1. 구현하기 쉽다.

2. timing이 정밀하다. 다른 timing mechanisms보다 성공적인 실행 사이에 정확한 시간차를 관리할 수 있다. 

3. cancellation이 중요할때 사용할 수 있다. 예를들어, 동작을 완료하기 전에 timer를 취소해야 하는 경우에 그렇다. 

 

C#의 다른 Timer

PeriodicTimer class외에 .NET에 event 기반의 System.Timers.Timer class가 있다. interval을 설정 후 event를 발생시키고 반복 event의 생성 조건을 제공한다. 

 

System.Threading.Timer도 있다. 

 

System.Windows.Forms.Timer는 Windows Forms appliation에서 사용된다. 

 

Web UI 앱에서 사용하는 System.Web.UI.Timer도 있다. 

 

PeriodicTimer가 다른 classes보다 우수하다. 

728x90
반응형