2012-05-26 12 views
7

Este es un problema grave en mi aplicación durante algunos meses sin encontrar una buena solución. Me di cuenta de que C# gestionaba la forma en que se transmite la clase Stream en WCF, sin tener en cuenta mi configuración.Flujo WCF - Velocidad límite

En primer lugar, tengo una clase que heredan de FileStream para que pueda ver cuánto se ha leído hasta ahora desde el lado del cliente en cualquier 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; 
     } 
    } 

En segundo lugar, a continuación es mi método de servicio de lectura de corriente del cliente que contiene el archivo. Mi problema principal es que FileStreamWatching.Read no se inicia cada vez que lo invoco desde este método a continuación, en lugar FileStreamWatching.Read comienza una vez por cada X veces que lo llamo .. Extraño.

* Mira la tarde hacia fuera puesto

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

Esta es la salida en el lado del cliente para cada vez que se activa FileStreamWatching.Read: (remmber la longitud búfer es de sólo 1000!)

Arr Longitud: 256, Leer: 256


Arr Longitud: 4096, Leer: 4096


Arr Longitud: 65536, Leer: 65536


Arr Longitud: 65536, Leer: 65536


Arr Longitud: 65536, Leído: 65536


Arr Longitud: 65536, Leer: 65536


.... Hasta el transfare expediente está completo.

Problemas:

  1. la longitud de la memoria intermedia que traje al método de lectura isnt 256/4096/65536. Es 1000.
  2. La lectura de la clase FileStreamWatching no se inicia cada vez que la llamo desde el servicio.

Mis objetivos:

  1. Controlando la cantidad que reacive desde el cliente para cada lectura.

  2. FileStreamWatching.Read se iniciará cada vez que lo llame desde el servicio.

Mi configuración del cliente:

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

Mi configuración de servicio (no hay ningún archivo de configuración aquí):

 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) - no debe compensar el incremento tras cada llamada? – Tisho

+0

@Tisho la aplicación probablemente cambia la compensación de cada llamada. Si lo hace o no, no influye en la pregunta de Stav en este punto del código. –

Respuesta

2

re: ¿por qué 256/4K/65535 ?

veo dos posibilidades pasando aquí:

  • FileStream La base está haciendo su propio búfer interno. Puede llamar internamente al read(array,offset,length) para llenar su memoria intermedia interna y luego devolver la parte que solicitó. Las llamadas internas terminan siendo recursivas, hasta que haya leído todo el archivo. Entonces su anulación deja de mostrar nada.
  • Hay otras stream.read() firmas que no se muestran como anuladas. Si alguna ruta de código termina llamando a uno de los otros métodos read, sus recuentos estarán desactivados.

re: MyStream no empezar de nuevo cada vez que

es el argumento MyStream siempre dispuesta? o se reutiliza para una nueva transmisión? Su código solo "se reinicia" en el constructor, así que sea seguro el objeto se desecha y se reconstruye cuando se cambian los flujos entrantes.

Puede probar el caso de EOF recursivo al mostrar también algo cuando se alcanza EOF.

Puede probar la recursión inesperada si agrega variables estáticas que cuentan tanto las llamadas de la aplicación al MyStream.Read como la entrada/salida del método. Si no coinciden, entonces FileStream realiza llamadas internas (accidentalmente recursivas).

-Jesse

Cuestiones relacionadas