using System.Collections.Generic;
private const int MSEC_TIME_EXTEND = 1000;
public enum TicketState: int { Unknown = 0, Queueing = 1, Serve = 2, Thrown = 3, Expired = 4};
private TicketState _state;
public DateTime BookTime;
public DateTime ServeTime;
public DateTime ExpiryTime;
_state = TicketState.Unknown; _id = 0; BookTime = DateTime.MinValue;
ServeTime = DateTime.MinValue; ExpiryTime = DateTime.MinValue;
_id = id; BookTime = DateTime.Now; _state = TicketState.Queueing;
if (_state == TicketState.Serve)
if (ExpiryTime < DateTime.Now)
_state = TicketState.Expired;
ServeTime = DateTime.Now;
ExpiryTime = DateTime.Now.AddMilliseconds(MSEC_TIME_EXTEND);
private static Dictionary<int, Ticket> _tickets = new Dictionary<int, Ticket>();
private static Random _rand = new Random();
private static int TicketIDToServe = 0;
public static int NumOfTickets
public static TicketState CurrentTicketState
if (_tickets.Count == 0) return TicketState.Unknown;
checkNextTicketsToServe();
return _tickets.ContainsKey(TicketIDToServe) ? _tickets[TicketIDToServe].State : TicketState.Unknown;
public static int GetTicket()
int id = _rand.Next(1, int.MaxValue);
while(_tickets.ContainsKey(id)) id = _rand.Next(1, int.MaxValue);
_tickets.Add(id, new Ticket(id));
public static TicketState CheckTicketState(int id)
checkNextTicketsToServe();
checkExpiredTicketsToThrow();
return _tickets.ContainsKey(id) ? _tickets[id].State : TicketState.Unknown;
private static void checkNextTicketsToServe()
if (!_tickets.ContainsKey(TicketIDToServe))
else if (_tickets[TicketIDToServe].State != TicketState.Serve)
if (!_tickets.ContainsKey(TicketIDToServe))
DateTime minBookTime = DateTime.MaxValue;
foreach (KeyValuePair<int, Ticket> kvp in _tickets)
if(kvp.Value.State == TicketState.Queueing && minBookTime > kvp.Value.BookTime)
minBookTime = kvp.Value.BookTime;
TicketIDToServe = kvp.Key;
if (_tickets.ContainsKey(TicketIDToServe))
_tickets[TicketIDToServe].State = TicketState.Serve;
private static void checkTicketsExpired()
int[] ids = _tickets.Where(t => t.Value.State == TicketState.Serve && t.Value.ExpiryTime < DateTime.Now).Select(t => t.Key).ToArray();
foreach(int id in ids) _tickets[id].State = TicketState.Expired;
private static void checkExpiredTicketsToThrow()
int[] ids = _tickets.Where(t => t.Value.State == TicketState.Expired).Select(t => t.Key).ToArray();
foreach(int id in ids) _tickets[id].State = TicketState.Thrown;
private static void trashThrownTickets()
int[] ids = _tickets.Where(t => t.Value.State == TicketState.Thrown).Select(t => t.Key).ToArray();
foreach(int id in ids) _tickets.Remove(id);
public static void ExtendExpiryTime(int id)
if(!_tickets.ContainsKey(id)) return;
if(_tickets[id].State != TicketState.Serve) return;
_tickets[id].ExpiryTime = DateTime.Now.AddMilliseconds(MSEC_TIME_EXTEND);
public static void ThrowTicket(int id)
if(!_tickets.ContainsKey(id)) return;
if(_tickets[id].State != TicketState.Serve) return;
_tickets[id].State = TicketState.Thrown;
if (TicketIDToServe == id) TicketIDToServe = 0;
public static void CancelTicket(int id)
if(!_tickets.ContainsKey(id)) return;
switch(_tickets[id].State)
case TicketState.Queueing:
_tickets[id].State = TicketState.Thrown;
if (TicketIDToServe == id) TicketIDToServe = 0;
public class HelloConsole
public static void Main(string[] args)
(new Thread(new ThreadStart(threadLoop))).Start();
Console.WriteLine ("Hello Mono World");
while(Console.ReadKey().KeyChar != 'q')
private static void threadLoop()
if (Ticket.CurrentTicketState == Ticket.TicketState.Unknown)
Console.WriteLine("{0} do loop", DateTime.Now.ToString("HH:mm:ss.fff"));
private static void doIt()
int id = Ticket.GetTicket();
while(Ticket.CheckTicketState(id) != Ticket.TicketState.Serve) Thread.Sleep(100);
Ticket.ExtendExpiryTime(id);
Console.WriteLine("{0} do task", DateTime.Now.ToString("HH:mm:ss.fff"));