네트워크

[C#] TaskTimer

우대비 2022. 6. 21. 21:16
반응형

    ---   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