반응형
--- Thread.Sleep(250); // 250ms 뒤에 실행..
Thread를 낭비하지 않는 효율적인 방법 TaskTimer
namespace Server
{
class Program
{
static Listener _listener = new Listener();
public static GameRoom Room = new GameRoom();
static void FlushRoom()
{
Room.Push(() => Room.Flush());
JobTimer.Instance.Push(FlushRoom, 250);
}
JobTimer.Instance.Push(FlushRoom, 250) == 250ms 뒤에 FlushRoom 실행이여~
static void Main(string[] args)
{
string host = Dns.GetHostName();
IPHostEntry ipHost = Dns.GetHostEntry(host);
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777);
_listener.Init(endPoint, () => { return SessionManager.Instance.Generate(); });
Console.WriteLine("Listening...");
FlushRoom();
while (true)
{
JobTimer.Instance.Flush();
}
}
}
}
JobTimer.Instance.Flush 무한 반복
namespace Server
{
struct JobTimerElem : IComparable<JobTimerElem>
{
public int execTick; // 실행시간
public Action action;
public int CompareTo(JobTimerElem other)
{
return other.execTick - execTick;
}
}
실행된 시간(execTick)과 일거리(Action)를 가지고 있는 구조체
class JobTimer
{
PriorityQueue<JobTimerElem> _pq = new PriorityQueue<JobTimerElem>();
object _lock = new object();
public static JobTimer Instance { get; } = new JobTimer();
public void Push(Action action, int tickAfter = 0)
{
JobTimerElem job;
job.execTick = System.Environment.TickCount + tickAfter;
job.action = action;
lock (_lock)
{
_pq.Push(job);
}
}
Push를 통해 일거리와 대기시간(tickAfter)가 넘어오면
일거리는 우선순위큐에 넣고 현재시간에 대기시간을 더해서 실행시간을 설정함
public void Flush()
{
while (true)
{
int now = System.Environment.TickCount;
JobTimerElem job;
lock (_lock)
{
if (_pq.Count == 0)
break;
job = _pq.Peek();
if (job.execTick > now)
break;
_pq.Pop();
}
job.action.Invoke();
}
}
}
}
실행시간이 되면 Pop, Invoke함
- lock안의 break는 lock을 탈출하는게 아닌 While을 탈출함
반응형
LIST
'네트워크' 카테고리의 다른 글
Google Protocol Buffers 설치 (0) | 2022.07.19 |
---|---|
[C#] 패킷 효율적으로 보내기 (0) | 2022.06.21 |
[C#] JobQueue (0) | 2022.06.20 |