2

私は辞書を初めて使用しましたが、辞書が非常に役立つことがわかりました。複数のクライアント接続を受け入れる ac# サーバー コンソールがあります。クライアントが接続するたびに、サーバー ディクショナリに追加されます。私は現在.net 3.5を使用しており(そしてすぐにアップグレードする予定はありません)、スレッドセーフでも静的でもない辞書を使用しています。通常、クライアントは自動的に終了しますが、フェイルセーフを実装する必要があります。クライアントが自動的に終了しない場合、タイマーを使用して 5 分後に接続を閉じたいと考えています。接続が閉じられたら、その項目をディクショナリから削除する必要があります。これを達成するために辞書とタイマーを機能させるにはどうすればよいですか? 立ち往生していて、リソースを使い果たしました。「_clientSockets.Remove(current)」を使用して接続を閉じています

以下は、私が現在持っている辞書とタイマーのコード スニペットです。

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);
        }
4

1 に答える 1

0

あなたの方法では、ディクショナリ内の特定のキーを特定のタイムアウトに関連付ける方法はありません。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);
   }
}
于 2013-10-22T20:56:16.940 に答える