초기커밋
This commit is contained in:
131
ServerCore/Timer/PeriodicTaskTimer.cs
Normal file
131
ServerCore/Timer/PeriodicTaskTimer.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
243
ServerCore/Timer/SimpleTimer.cs
Normal file
243
ServerCore/Timer/SimpleTimer.cs
Normal file
@@ -0,0 +1,243 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
|
||||
namespace ServerCore;
|
||||
|
||||
//=============================================================================================
|
||||
// 간단한 로직을 위한 타이머 클래스 이다.
|
||||
//
|
||||
// author : kangms
|
||||
//
|
||||
//=============================================================================================
|
||||
|
||||
public class SimpleTimer
|
||||
{
|
||||
private DateTime m_begin_timestamp = DateTime.MinValue;
|
||||
private DateTime m_end_timestamp = DateTime.MinValue;
|
||||
|
||||
private Int64 m_time_limit_msec = 0;
|
||||
|
||||
private bool m_is_paused = false;
|
||||
private DateTime m_pause_timestamp = new DateTime();
|
||||
private Int64 m_pause_total_msec = 0;
|
||||
|
||||
private bool m_active = false;
|
||||
|
||||
public SimpleTimer()
|
||||
{
|
||||
}
|
||||
|
||||
public SimpleTimer(Int64 timeLimitMSec)
|
||||
{
|
||||
setTimeLimitMSec(timeLimitMSec);
|
||||
}
|
||||
|
||||
public void setTimer(Int64 timeLimitMSec)
|
||||
{
|
||||
setTimer(0, timeLimitMSec);
|
||||
}
|
||||
|
||||
public void setTimer(Int64 beginUtcTick, Int64 timeLimitMSec)
|
||||
{
|
||||
m_begin_timestamp = beginUtcTick > 0 ? new DateTime(beginUtcTick) : DateTime.UtcNow;
|
||||
m_time_limit_msec = timeLimitMSec;
|
||||
|
||||
m_is_paused = false;
|
||||
m_pause_total_msec = 0;
|
||||
|
||||
m_end_timestamp = DateTime.MinValue;
|
||||
}
|
||||
|
||||
public void activate(Int64 timeLimitMSec = 0)
|
||||
{
|
||||
m_active = true;
|
||||
if (timeLimitMSec != 0)
|
||||
{
|
||||
setTimer(0, timeLimitMSec);
|
||||
}
|
||||
else
|
||||
{
|
||||
reset(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void activate(Int64 beginUtcTick, Int64 timeLimitMSec = 0)
|
||||
{
|
||||
m_active = true;
|
||||
if (timeLimitMSec != 0)
|
||||
{
|
||||
setTimer(beginUtcTick, timeLimitMSec);
|
||||
}
|
||||
else
|
||||
{
|
||||
reset(beginUtcTick);
|
||||
}
|
||||
}
|
||||
|
||||
public bool isActive()
|
||||
{
|
||||
return m_active;
|
||||
}
|
||||
|
||||
public void deactivate()
|
||||
{
|
||||
m_active = false;
|
||||
m_end_timestamp = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
public void setTimeLimitMSec(Int64 limitMSec)
|
||||
{
|
||||
m_time_limit_msec = limitMSec;
|
||||
|
||||
m_time_limit_msec = Math.Max(m_time_limit_msec, 0);
|
||||
}
|
||||
|
||||
public void incTimeLimitMSec(Int64 incMSec)
|
||||
{
|
||||
m_time_limit_msec += incMSec;
|
||||
|
||||
m_time_limit_msec = Math.Max(m_time_limit_msec, 0);
|
||||
}
|
||||
|
||||
public Int64 getTimeLimitMSec()
|
||||
{
|
||||
return m_time_limit_msec;
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
setTimer(m_time_limit_msec);
|
||||
}
|
||||
|
||||
public void reset(Int64 beginUtcTick)
|
||||
{
|
||||
setTimer(beginUtcTick, m_time_limit_msec);
|
||||
}
|
||||
|
||||
public bool expired()
|
||||
{
|
||||
if (false == isActive())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (true == isPause())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (DateTime.UtcNow - m_begin_timestamp).TotalMilliseconds > (m_pause_total_msec + m_time_limit_msec);
|
||||
}
|
||||
|
||||
public void pause()
|
||||
{
|
||||
if (isPause())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_is_paused = true;
|
||||
m_pause_timestamp = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
public bool isPause()
|
||||
{
|
||||
return m_is_paused;
|
||||
}
|
||||
|
||||
public void unpause()
|
||||
{
|
||||
if (false == isPause())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pause_time = (DateTime.UtcNow - m_pause_timestamp).TotalMilliseconds;
|
||||
m_pause_total_msec += (Int64)pause_time;
|
||||
|
||||
m_is_paused = false;
|
||||
}
|
||||
|
||||
public Int64 getTotalTimeMSec()
|
||||
{
|
||||
if (!isActive())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var end_time = m_begin_timestamp.AddMilliseconds(m_time_limit_msec);
|
||||
|
||||
var total_time = (end_time - m_begin_timestamp).TotalMilliseconds;
|
||||
|
||||
total_time = Math.Max(total_time, 0);
|
||||
|
||||
return (Int64)total_time;
|
||||
}
|
||||
|
||||
public Int64 getElapsedPauseTimeMSec()
|
||||
{
|
||||
if (false == isActive())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var pause_time = m_pause_total_msec;
|
||||
|
||||
if (true == isPause())
|
||||
{
|
||||
pause_time += (Int64)((DateTime.UtcNow - m_pause_timestamp).TotalMilliseconds);
|
||||
}
|
||||
|
||||
pause_time = Math.Max(pause_time, 0);
|
||||
|
||||
return (Int64)pause_time;
|
||||
}
|
||||
|
||||
public bool isOn()
|
||||
{
|
||||
if (false == expired())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public DateTime getStartedTime() => m_begin_timestamp;
|
||||
public DateTime getEndTime() => m_end_timestamp;
|
||||
|
||||
public Int64 getRemainTimeMSec()
|
||||
{
|
||||
if (false == isActive())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var pause_time = getElapsedPauseTimeMSec();
|
||||
|
||||
TimeSpan time_span = DateTime.UtcNow - m_begin_timestamp;
|
||||
var remain_time = m_time_limit_msec + pause_time - (Int64)time_span.TotalMilliseconds;
|
||||
remain_time = Math.Max(remain_time, 0);
|
||||
|
||||
return remain_time;
|
||||
}
|
||||
|
||||
public Int64 getElapsedTimeMSec()
|
||||
{
|
||||
if (false == isActive())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
TimeSpan time_span = DateTime.UtcNow - m_begin_timestamp;
|
||||
return (Int64)time_span.TotalMilliseconds;
|
||||
}
|
||||
|
||||
}
|
||||
160
ServerCore/Timer/StopwatchTimer.cs
Normal file
160
ServerCore/Timer/StopwatchTimer.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
|
||||
namespace ServerCore;
|
||||
|
||||
//=============================================================================================
|
||||
// StopWatch 모듈을 활용한 타이머 기능을 제공하는 클래스 이다.
|
||||
//
|
||||
// author : kangms
|
||||
//=============================================================================================
|
||||
|
||||
public class StopwatchTimer
|
||||
{
|
||||
private readonly System.Diagnostics.Stopwatch m_stop_watch = new System.Diagnostics.Stopwatch();
|
||||
private readonly TimeSpan m_interval = default(TimeSpan);// 체크 주기
|
||||
private readonly bool m_is_manual_restart = false; // 수동 재시작 여부
|
||||
private bool m_force_on = false;
|
||||
|
||||
public StopwatchTimer(TimeSpan intreval, bool is_pause = false, bool is_manual_restart = false)
|
||||
{
|
||||
m_interval = intreval;
|
||||
m_is_manual_restart = is_manual_restart;
|
||||
|
||||
if (is_pause)
|
||||
{
|
||||
pause();
|
||||
}
|
||||
else
|
||||
{
|
||||
resume();
|
||||
}
|
||||
}
|
||||
|
||||
public StopwatchTimer(Int64 interval_milliseconds, bool is_pause = false, bool is_manual_restart = false)
|
||||
: this(new TimeSpan(interval_milliseconds * TimeSpan.TicksPerMillisecond), is_pause, is_manual_restart)
|
||||
{
|
||||
}
|
||||
|
||||
public StopwatchTimer(float intreval_seconds, bool is_pause = false, bool is_manual_restart = false)
|
||||
: this((Int64)(intreval_seconds * 1000.0f), is_pause, is_manual_restart)
|
||||
{
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
// 지정된 시간 만큼 경과 되었는지 검사한다.
|
||||
//=========================================================================================
|
||||
public bool isOn()
|
||||
{
|
||||
if (m_force_on)
|
||||
{
|
||||
m_force_on = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_stop_watch.IsRunning == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Elapsed < m_interval)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_is_manual_restart)
|
||||
{
|
||||
// 한번만 실행되고 멈춘다, 다시 시작하려면, restart를 호출해야 한다.
|
||||
pause();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 자동리셋이면 재시작
|
||||
restart();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 강제로 타이머를 On상태로 만든다.
|
||||
public void forceOn()
|
||||
{
|
||||
m_force_on = true;
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
// isOn의 기능과, 경과시간을 얻어온다.
|
||||
//=========================================================================================
|
||||
public bool isOn(out TimeSpan elapsed)
|
||||
{
|
||||
elapsed = Elapsed;
|
||||
return isOn();
|
||||
}
|
||||
|
||||
|
||||
//=========================================================================================
|
||||
// 타이머가 멈춰있는가?
|
||||
//=========================================================================================
|
||||
public bool isPaused()
|
||||
{
|
||||
return m_stop_watch.IsRunning == false;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================================================
|
||||
// 타이머가 실행중인가?
|
||||
//=========================================================================================
|
||||
public bool isRunning()
|
||||
{
|
||||
return m_stop_watch.IsRunning;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================================================
|
||||
// 일시정지
|
||||
//=========================================================================================
|
||||
public void pause()
|
||||
{
|
||||
m_stop_watch.Stop();
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
// 시작 또는 일시정지를 종료하고 다시 시작
|
||||
//=========================================================================================
|
||||
public void resume()
|
||||
{
|
||||
m_stop_watch.Start();
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
// 타이머를 초기화하고, 시작
|
||||
//=========================================================================================
|
||||
public TimeSpan restart()
|
||||
{
|
||||
TimeSpan elapsed = m_stop_watch.Elapsed;
|
||||
m_stop_watch.Reset();
|
||||
m_stop_watch.Start();
|
||||
return elapsed;
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
// 경과 시간 조회
|
||||
//=========================================================================================
|
||||
public TimeSpan Elapsed
|
||||
{
|
||||
get { return m_stop_watch.Elapsed; }
|
||||
}
|
||||
//=========================================================================================
|
||||
// 남은 시간 조회
|
||||
//=========================================================================================
|
||||
public TimeSpan RemainTime
|
||||
{
|
||||
get { return Elapsed.TotalSeconds > 0 ? (m_interval > Elapsed ? m_interval - Elapsed : new TimeSpan(0)) : new TimeSpan(0); }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user