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 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 tasks) { tasks.Add(taskTimer.getTask()); } }