2012-03-02 5 views
5

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

Все примеры, которые я нахожу, не имеют реализации тайм-аута.

Может ли кто-нибудь дать мне рабочий пример и/или указать мне пример, который показывает это?

+0

Вы пытаетесь использовать прямые именованные трубы, или вы смотрите на использование WCF над именованными трубами? –

+0

@AdamGritt: прямые именованные трубы. –

ответ

3

Что вам, вероятно, придется делать, это асинхронное чтение и запись с помощью NamedPipeClientStream.BeginRead и NamedPipeClientStream.BeginWrite; то таймер будет использоваться для обнаружения, когда данные не были отправлены или получены в течение определенного периода времени.

Когда данные отправляются или принимаются, поле DateTime будет установлено в DateTime.Now, и каждое выполнение таймера проверяет это поле, чтобы определить, происходит ли тайм-аут. Если происходит, NamedPipeClientStream может быть закрыт, и могут быть обнаружены исключения из NamedPipeClientStream.EndRead и NamedPipeClientStream.EndWrite.

У меня пока нет готового примера, но я смогу работать над ним, если вам это нужно. Надеюсь, это поможет вам в то же время.


Это очень грубый пример кода. Необходимо выполнить гораздо больше, например, реализовать IDisposable и добавить методы записи. Это должно помочь проиллюстрировать эту идею. Лучше всего использовать этот код в качестве модели, а не использовать его напрямую. Я проверил код, чтобы узнать, читает ли он.

//this is a very rough model of how to do it. a lot more would need to be implemented 
//i'm assuming you plan to continuously read from it. i can think up another example if you're not 
//also not thread safe 
public class MyPipeClient 
{ 
    NamedPipeClientStream PipeClient = new NamedPipeClientStream("testpipe1"); 
    Timer TimeoutTimer; 
    DateTime LastRead; 
    const int TimeoutSeconds = 120; //2 mins 

    //will connect and start receiving 
    public void Connect() 
    { 
     PipeClient.Connect(); 
     LastRead = DateTime.Now; 

     TimeoutTimer = new Timer(TimeoutCheck, this, 0, 1000); //check every second 

     Read(this); 
    } 

    public void Disconnect() 
    { 
     PipeClient.Close(); PipeClient = null; 
     TimeoutTimer.Dispose(); TimeoutTimer = null; 
    } 

    static void Read(MyPipeClient client) 
    { 
     PipeState state = new PipeState(client); 

     try 
     { 
      client.PipeClient.BeginRead(state.Buffer, 0, state.Buffer.Length, ReadCallback, state); 
     } 
     catch (InvalidOperationException) //disconnected/disposed 
     { 
      return; 
     } 
    } 

    static void ReadCallback(IAsyncResult ar) 
    { 
     PipeState state = (PipeState)ar.AsyncState; 
     MyPipeClient client = state.Client; 

     client.LastRead = DateTime.Now; 

     int bytesRead; 

     try 
     { 
      bytesRead = client.PipeClient.EndRead(ar); 
     } 
     catch (IOException) //closed 
     { 
      return; 
     } 

     if (bytesRead > 0) 
     { 
      byte[] data = state.Buffer; 

      //TODO: something 
     } 
     else //i've never used pipes, so i'm assuming this behavior exists with them 
     { 
      client.Disconnect(); 
      return; 
     } 

     Read(client); 
    } 

    static void TimeoutCheck(object state) 
    { 
     MyPipeClient client = (MyPipeClient)state; 

     TimeSpan timeSinceLastRead = DateTime.Now - client.LastRead; 

     if (timeSinceLastRead.TotalSeconds > TimeoutSeconds) 
     { 
      client.Disconnect(); 
     } 
    } 
} 

class PipeState 
{ 
    public byte[] Buffer = new byte[4096]; 
    public MyPipeClient Client; 

    public PipeState(MyPipeClient client) 
    { 
     Client = client; 
    } 
} 
+0

Отличный пример; Я попробую это. –

Смежные вопросы