Files
caliverse_server/ServerCore/Timer/PeriodicTaskTimer.cs
2025-05-01 07:20:41 +09:00

132 lines
3.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.Xml.Linq;
namespace ServerCore;
//=============================================================================================
// 주기적 Task 타이머 클래스 이다.
//
// author : kangms
//
//=============================================================================================
public class PeriodicTaskTimer : IAsyncDisposable
{
private readonly string m_name;
private readonly System.Threading.PeriodicTimer m_timer;
private readonly Task m_timer_task;
private readonly CancellationTokenSource m_cts;
public delegate Task FnFunction();
private readonly FnFunction m_fn_alarm_function;
public PeriodicTaskTimer(string name, Int32 intervalSec, FnFunction fnAlarmFunction)
{
m_name = name;
m_cts = new CancellationTokenSource();
m_timer = new System.Threading.PeriodicTimer(TimeSpan.FromSeconds(intervalSec));
m_fn_alarm_function = fnAlarmFunction;
m_timer_task = handleTimerAsync(m_timer, m_cts.Token);
}
//=============================================================================================
// CancellationTokenSource 를 외부에서 제어할 때 사용한다.
//=============================================================================================
public PeriodicTaskTimer(string name, double intervalMSec, CancellationTokenSource cts, FnFunction fnAlarmFunction)
{
m_name = name;
m_cts = cts;
m_timer = new System.Threading.PeriodicTimer(TimeSpan.FromMilliseconds(intervalMSec));
m_fn_alarm_function = fnAlarmFunction;
m_timer_task = handleTimerAsync(m_timer, m_cts.Token);
}
private async Task handleTimerAsync(System.Threading.PeriodicTimer timer, CancellationToken cancel = default)
{
try
{
while (await timer.WaitForNextTickAsync(cancel))
{
await Task.Run(() => m_fn_alarm_function.Invoke());
}
}
catch (OperationCanceledException e)
{
var msg = $"PeriodicTaskTimer cancel Operation !!! : exception:{e} - {m_name}";
Log.getLogger().info(msg);
}
catch (Exception e)
{
var err_msg = $"PeriodicTaskTimer exception !!! : exception:{e} - {m_name}";
Log.getLogger().error(err_msg);
}
}
public void cancelTimer() => m_cts.Cancel();
//for IAsyncDisposable.DisposeAsync()
public async ValueTask DisposeAsync()
{
m_timer.Dispose();
await m_timer_task;
GC.SuppressFinalize(this);
}
public System.Threading.PeriodicTimer getPeriodicTimer() => m_timer;
public Task getTask() => m_timer_task;
}
//=============================================================================================
// 주기적 Task 타이머 지원 클래스 이다.
//
// author : kangms
//
//=============================================================================================
public static class PeriodicTaskHelper
{
public static async Task runTask(Func<Task> action, TimeSpan interval, CancellationToken cancellationToken = default)
{
using var timer = new PeriodicTimer(interval);
while (cancellationToken.IsCancellationRequested == false)
{
try
{
await action();
await timer.WaitForNextTickAsync(cancellationToken);
}
catch (OperationCanceledException e)
{
var msg = $"PeriodicTaskHelper cancel Operation !!! : Msg:{e.Message}";
Log.getLogger().info(msg);
break;
}
catch (Exception e)
{
var err_msg = $"PeriodicTaskHelper exception !!! : errMsg:{e.Message}";
Log.getLogger().error(err_msg);
throw;
}
}
}
public static void bindToTasks(this PeriodicTaskTimer taskTimer, List<Task> tasks)
{
tasks.Add(taskTimer.getTask());
}
}