2012-05-26 8 views
7

Questo è un problema grave nella mia applicazione per alcuni mesi senza trovare alcuna buona soluzione. Ho notato che C# gestisce il modo in cui la classe Stream è in streaming in WCF, senza considerare la mia configurazione.Streaming WCF - Velocità limite

In primo luogo, ho una classe che ereditano da FileStream in modo da poter guardare quanto è stato letto fino ad ora dal lato client in qualsiasi momento:

public class FileStreamWatching : FileStream 
    { 
     /// <summary>   
     /// how much was read until now   
     /// </summary>   
     public long _ReadUntilNow { get; private set; } 
     public FileStreamWatching(string Path, FileMode FileMode, FileAccess FileAccess) 
      : base(Path, FileMode, FileAccess) 
     { 
      this._ReadUntilNow = 0; 
     } 
     public override int Read(byte[] array, int offset, int count) 
     { 
      int ReturnV = base.Read(array, offset, count); 
      //int ReturnV = base.Read(array, offset, count); 
      if (ReturnV > 0) 
      { 
       _ReadUntilNow += ReturnV; 
       Console.WriteLine("Arr Lenght: " + array.Length); 
       Console.WriteLine("Read: " + ReturnV); 
       Console.WriteLine("****************************"); 
      } 
      return ReturnV; 
     } 
    } 

In secondo luogo, al di sotto è il mio metodo di servizio della lettura flusso del cliente che contengono il file. Il mio problema principale è che FileStreamWatching.Read non si avvia ogni volta che lo richiama da questo metodo qui sotto, invece FileStreamWatching. Lancia l'avvio una volta per ogni X volte che lo chiamo .. Strano.

* sguardo al fuori messo tardi

public void Get_File_From_Client(Stream MyStream) 
    { 
     using (FileStream fs = new FileStream(@"C:\Upload\" + "Chat.rar", FileMode.Create)) 
     { 
      byte[] buffer = new byte[1000]; 
      int bytes = 0; 
      while ((bytes = MyStream.Read(buffer, 0, buffer.Length)) > 0) 
      { 
       fs.Write(buffer, 0, bytes); 
       fs.Flush(); 
      } 
     } 
    } 

Questa è l'uscita sul lato client per ogni volta che viene attivato FileStreamWatching.Read: (Remmber la lunghezza del buffer è solo 1000!)

Arr Lunghezza: 256, Leggi: 256


Arr Lunghezza: 4096, Leggi: 4096


Arr Lunghezza: 65536, Leggi: 65536


Arr Lunghezza: 65536, Leggi: 65536


Arr Lunghezza: 65536, Letto: 65536


Arr Lunghezza: 65536, Leggi: 65536


.... Fino a quando il file transfare è completo.

Problemi:

  1. la lunghezza del buffer che ho portato al metodo read isnt 256/4096/65536. È 1000.
  2. La lettura dalla classe FileStreamWatching non viene avviata ogni volta che la chiamo dal servizio.

I miei obiettivi:

  1. gestente da quanto ho reacive dal cliente per ogni lettura.

  2. Il FileStreamWatching.Read verrà avviato ogni volta che lo chiamo dal servizio.

La mia configurazione del client:

<configuration> 
    <system.serviceModel> 
     <bindings> 
      <basicHttpBinding> 
       <binding name="BasicHttpBinding_IJob" transferMode="Streamed"/> 
      </basicHttpBinding> 
     </bindings> 
     <client> 
      <endpoint address="http://localhost:8080/Request2" binding="basicHttpBinding" 
       bindingConfiguration="BasicHttpBinding_IJob" contract="ServiceReference1.IJob" 
       name="BasicHttpBinding_IJob" /> 
     </client> 
    </system.serviceModel> 
</configuration> 

La mia configurazione del servizio (non ci sono file di configurazione qui):

 BasicHttpBinding BasicHttpBinding1 = new BasicHttpBinding(); 
     BasicHttpBinding1.TransferMode = TransferMode.Streamed; 
     // 
     BasicHttpBinding1.MaxReceivedMessageSize = int.MaxValue; 
     BasicHttpBinding1.ReaderQuotas.MaxArrayLength = 1000; 
     BasicHttpBinding1.ReaderQuotas.MaxBytesPerRead = 1000; 
     BasicHttpBinding1.MaxBufferSize = 1000; 
     // 
     ServiceHost host = new ServiceHost(typeof(JobImplement), new Uri("http://localhost:8080")); 
     // 
     ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); 
     behavior.HttpGetEnabled = true; 
     // 
     host.Description.Behaviors.Add(behavior); 
     ServiceThrottlingBehavior throttle = new ServiceThrottlingBehavior(); 
     throttle.MaxConcurrentCalls = 1; 
     host.Description.Behaviors.Add(throttle); 
     // 
     // 
     host.AddServiceEndpoint(typeof(IJob), BasicHttpBinding1, "Request2"); 
     host.Open(); 
+0

MyStream.Read (buffer, 0, buffer.Length) - qualora l'incremento di offset dopo ogni chiamata? – Tisho

+0

@Tisho l'applicazione probabilmente cambia l'offset di ogni chiamata. Che lo faccia o no non influenza la domanda di Stav a questo punto del codice. –

risposta

2

Re: 256/4K/65535 ?

vedo due possibilità succedendo qui:

  • La base FileStream sta facendo il proprio buffer interno. Potrebbe essere chiamato internamente allo read(array,offset,length) per riempire il buffer interno, quindi restituire la parte richiesta. Le chiamate interne finiscono per essere ricorsive, fino a quando non ha letto l'intero file. Quindi il tuo override smette di visualizzare qualsiasi cosa.
  • Ci sono altre firme stream.read() che non vengono visualizzate come sovrascritte. Se qualche percorso di codice finisce per chiamare uno degli altri metodi read, allora i tuoi conteggi saranno spenti.

Re: MyStream non ricominciando ogni volta

è l'argomento MyStream mai smaltito? o viene riutilizzato per un nuovo stream? Il tuo codice solo "riavvia" nel costruttore, quindi sii sicuro l'oggetto viene eliminato e ricostruito quando si modificano i flussi in entrata.

È possibile eseguire il test del caso EOF ricorsivo visualizzando anche qualcosa quando viene raggiunto EOF.

È possibile verificare la ricorsione inattesa se si aggiungono variabili statiche che contano sia le chiamate dell'applicazione a MyStream.Read che il metodo di entrata/uscita. Se non corrispondono, allora FileStream sta effettuando chiamate interne (casualmente ricorsive).

-Jesse