2012-03-02 15 views
5

Non riesco a trovare il modo migliore per implementare IPC con named pipe con una robusta gestione del timeout. Non intendo il timeout per stabilire una connessione ma il timeout per i flussi di lettura/scrittura.Esempio di pipe denominate IPC con timeout di lettura/scrittura

Tutti gli esempi che ho trovato non hanno un'implementazione di timeout.

Qualcuno può darmi un esempio funzionante e/o indicarmi un esempio che mostri questo?

+0

Si sta tentando di utilizzare Straight Named Pipes o si sta cercando di utilizzare WCF su Named Pipes? –

+0

@AdamGritt: pipe con nome diretto. –

risposta

3

Quello che dovrete probabilmente fare è leggere e scrivere asincroni con NamedPipeClientStream.BeginRead e NamedPipeClientStream.BeginWrite; verrà quindi utilizzato un timer per rilevare quando i dati non sono stati inviati o ricevuti per un periodo di tempo.

Ogni volta che i dati vengono inviati o ricevuti, un campo DateTime verrà impostato su DateTime.Now e ciascuna esecuzione del timer controllerà su quel campo per determinare se si verifica un timeout. In tal caso, è possibile chiudere NamedPipeClientStream e recuperare le eccezioni da NamedPipeClientStream.EndRead e NamedPipeClientStream.EndWrite.

Non ho ancora un esempio funzionante pronto, ma ci riuscirò a lavorarci su uno se ne avete bisogno. Spero che questo ti possa aiutare nel frattempo.


Questo è un codice di esempio molto approssimativo. Molto altro dovrebbe essere fatto, come implementare IDisposable e aggiungere metodi di scrittura. Questo dovrebbe aiutare a illustrare l'idea, però. Probabilmente sarebbe meglio usare questo codice come modello, piuttosto che usarlo direttamente. Ho testato il codice per vedere se legge.

//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

Ottimo esempio; Ci proverò. –

Problemi correlati