如何将计时器与字典一起使用

本文关键字:一起 字典 计时器 | 更新日期: 2023-09-27 18:36:24

我是字典的新手,发现它们非常有用。我有一个接受多个客户端连接的 c# 服务器控制台。每次客户端连接时,它都会添加到服务器字典中。我目前正在使用 .net 3.5(并且不会很快升级),并且正在使用既不线程安全也不静态的字典。客户端通常会自行退出,但我需要实现故障保护。如果客户端没有自行退出,我想使用计时器在 5 分钟后关闭连接。关闭连接后,需要从字典中删除该项。我将如何使我的字典和计时器工作以实现此目的?我被困住了,已经用尽了我的资源。我正在使用"_clientSockets.删除(当前)"来关闭连接

以下是我目前拥有的字典和计时器的代码片段:

private static Timer aTimer = new System.Timers.Timer(10000);
        private static Object thisLock = new Object();
        public static void Main()
        {
            Console.ReadKey();
            aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
            aTimer.Interval = 1000 * 60 * 5;
            aTimer.Enabled = true;
            Console.WriteLine("Press the Enter key to exit the program.");
            Console.WriteLine(DateTime.Now);
            Console.ReadLine();
        Dictionary<int, DateTime> ServDict = new Dictionary<int, DateTime>();
            ServDict.Add(9090, DateTime.Now.AddMinutes(5));
            ServDict.Add(9091, DateTime.Now.AddMinutes(5));
            ServDict.Add(9092, DateTime.Now.AddMinutes(5));
            ServDict.Add(9093, DateTime.Now.AddMinutes(5));
            ServDict.Add(9094, DateTime.Now.AddMinutes(5));
            Console.WriteLine("Time List");
                foreach (KeyValuePair<int, DateTime> time in ServDict)
                {
                    Console.WriteLine("Port = {0}, Time in 5 = {1}",
                        time.Key, time.Value);
                }
            Console.ReadKey();
        }
        private static void OnTimedEvent(object source, ElapsedEventArgs e)
        {           
            Console.WriteLine("The trigger worked, The Elapsed event was raised at {0}", e.SignalTime);
            Console.WriteLine(DateTime.Now);
        }

如何将计时器与字典一起使用

使用您的方法,无法将字典中的特定键与特定超时相关联。您必须每 n 秒"轮询"一次字典(其中 n 是您可以错过 5 分钟标记多少),并检查自收到数据以来已经过去了多长时间。

更好的解决方案可能是将客户端包装在一个类中(并且只保存一个列表,您可能甚至不需要字典)?在这种情况下,类的每个实例都可以保存一个"超时"计时器,该计时器在 5 分钟后经过并调用关闭连接函数。同一事件处理程序还可以引发一个事件,该事件是保存所有客户端的类注册的,以便它可以将其从活动列表中删除。

每当收到数据时,客户端类都会重置计时器。这可以通过使用System.Threading.Timer并在其上调用Change(dueTime,period)轻松实现。

类似以下内容的内容应该有效:

public class Client
{
  public event Action<Client> Timeout;
  System.Threading.Timer timeoutTimer;
  public Client()
  {
    timeoutTimer = new Timer(timeoutHandler, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
  }
  public void onDataRecieved()
  {
     timeoutTimer.Change(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
  }
  public void timeoutHandler(object data)
  {
     CloseConnection();
     if (Timeout != null)
        Timeout(this);
  }
}
class Program
{
   List<Client> connectedClients = new List<Client>
   void OnConnected(object clientData)
   {
      Client newClient = new Client();
      newClient.Timeout += ClientTimedOut;
      connectedClients.Add(newClient);
   }
   void ClientTimedOut(Client sender)
   {
      connectedClients.Remove(sender);
   }
}