2015-07-07 10 views
0

У меня есть клиент-серверное приложение, и я хочу периодически проверять, если клиент отключился от сервера.StopWatch в отдельной перезагрузке потока

Я решил, что проверю входящие пакеты. Если я получил какое-либо время, позвольте сказать 15 секунд, у меня есть действующее соединение, , если нет, я отключился и попытаюсь снова подключиться.

До сих пор у меня есть этот пример кода (это образец воссозданной из моего кода):

namespace TimerExample 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      HandlePackets(); 
     } 

     public void HandlePackets() 
     { 
      //code that handles incomming packets 
      foo test = new foo(); 

      test.StartThread(); 
     } 
    } 

    class foo 
    { 
     public bool _isRunning { get; set; } 
     private Stopwatch sw { get; set; } 

     public void StartThread() 
     { 
      this._isRunning = true; 
      new Thread(new ThreadStart(this.DoWork)).Start(); 

      this.sw.Restart(); 
     } 

     public void StopThread() 
     { 
      this._isRunning = false; 
      this.sw.Stop(); 
     } 

     private void DoWork() 
     { 
      while (this._isRunning) 
      { 
       Console.WriteLine("Elapsed in miliseconds: " + this.GetRuntime().ToString()); 

       if (GetRuntime() > 15000) 
       { 
        Console.WriteLine("Client disconnected.... restarting"); 
        this.StopThread(); 
       } 

       Thread.Sleep(1000); 
      } 
     } 

     public long GetRuntime() 
     { 
      return this.sw.ElapsedMilliseconds; 
     } 

     public foo() 
     { 
      _isRunning = false; 
      sw = new Stopwatch(); 
     } 
    } 
} 

То, что я хочу для кода, который будет делать это: Функция HandlePackets будет выполняться каждый раз, когда пакет прибудет. Внутри этой функции я позвоню функции StartThread, которая будет работать Stopwatch в отдельной теме, и этот процесс продолжится до тех пор, пока stopwatch истекшее время в миллисекундах не будет больше, чем позволяет сказать 15 секунд.

Если это произойдет, я позвоню Reconnect.

Таким образом, в основном таймер будет перезапускаться каждый раз, когда принимается пакет и будет повторно подключаться, если ElapsedTime будет больше 15 секунд.

+0

На самом деле я не вижу здесь вопроса. Что ты спрашиваешь? Что не так с кодом, который у вас есть? –

ответ

1

Существует несколько способов реализации этого механизма.

Создание нити - худшее. Будьте осторожны - доступ к членам экземпляра секундомера из нескольких потоков небезопасен.

Одно из простых и простых решений заключается в создании ThreadPool Timer, который тикает, скажем, каждые 15 секунд и проверяет логическую переменную через Volatile.Read. Когда логическая переменная False - вы можете повторно подключиться. Из потолка приемника вам просто нужно установить переменную, используя Volatile.Write true. Это не потребляет ресурсы при получении (почти).

Во многих реализациях могут быть расы из-за механизма повторного подключения, который может начать миг до появления нового пакета. Самый простой и мошеннический способ улучшить это - остановить таймер прямо перед тем, как вы решите повторно подключиться и запустить его снова, как только соединение будет завершено. Вы должны понимать, что нет способа решить эту проблему с ложным повторным подключением.

Описанные выше метод работает довольно много, как WatchDog

С точки зрения дизайна, я бы порекомендовал вам создать классы: приемник и сторожевого ConnectionManager

// Receives and processes data 
class Receiver : IDisposable 
{ 
    public Receiver(WatchDog watchDog); 
    public void LoopReceive(); // Tick watch dog on every packet 
    public void Dispose(); 
} 

// Setups timer and periodically checks if receiver is alive. 
// If its not, it asks manager to reconnect and disposes receiver 
class WatchDog : IDisposable 
{ 
    public WatchDog(ConnectionFactory factory); 
    // Setups timer, performs Volatile.Read and if receiver is dead, call dispose on it and ask manager to reconnect. 
    public void StartWatching(IDisposable subject); 
    public void Tick(); // Volatile.Write 
    public void Dispose(); 
} 

// Can re-connect and create new instances of timer and watchdog 
// Holds instance variable of receiver created 
class ConnectionManager 
{ 
    public void Connect(); 
    // disposes watch dog and calls connect 
    public void ReConnect(WatchDog watchDog); 
} 

PS:. Volatile * можно заменить летучим ключевое слово переменная флага