2012-06-25 12 views
6

Una limitación de la implementación de protobuf-net es que llama a las secuencias subyacentes de forma síncrona. Al no ofrecer una API asíncrona, p. BeginSerialize/EndSerialize o un equivalente de TPL, estamos obligados a atar un hilo esperando la E/S de flujo sincrónico.serialización de protobuf asincrónica

¿Hay algún plan para ofrecer métodos asincrónicos en protobuf-net o, alternativamente, formas creativas para solucionar este problema?

Respuesta

5

No, eso no es compatible actualmente y sería un lote de trabajo.

Mi sugerencia sería: datos del buffer sí mismo utilizando las API asíncronas, y luego cuando usted tiene los datos, usar algo como un MemoryStream deserializar ...

En mi defensa, no estoy al tanto de cualquier otro serializador que ofrece una API asíncrona aquí. En particular, cuando se habla de transmisiones lentas/asincrónicas, ese usualmente significa "red": y usted generalmente tiene el problema de "enmarcar" para considerarlo allí; protobuf-net no conocerá sus requisitos de estructura ...

+0

¿Hay algún flujo de almacenamiento intermedio genérico que bloquee la asincronía? Actualmente estoy usando un enfoque MemoryStream, pero quiero deserializar parcialmente el encabezado del archivo (como en http://stackoverflow.com/questions/13342318/deserialize-part-of-a-binary-file) y no tengo forma de saber cuántos bytes necesito para recuperar Async, solo el deserializador lo sabe. – tozevv

+0

@tozevv sync-over-async? que * puede * ser bastante peligroso, para ser honesto. ¿Cuál es la fuente de datos subyacente aquí? ¿Qué fuente asíncrona proporciona los datos? Una secuencia de sincronización sobre sincronización podría probablemente * escribirse * fácilmente. –

+0

Sí, no tengo ningún problema con la escritura. Estoy leyendo un archivo con un encabezado y un cuerpo. Si sé que el tamaño del encabezado es trivial para leer el encabezado (ReadAsync) primero y solo si el encabezado cumple una condición determinada, lea el resto del cuerpo también Async. Tanto el encabezado como los contenidos están siendo serializados usando su excelente (gracias por eso) implementación de búferes de protocolo. – tozevv

2

Puede esperar Task.Run que ejecutará el código síncrono en el grupo de subprocesos. No es la solución más eficiente, pero es mejor que bloquear. Incluso puede enviar su propia CancellationToken-Task.Run:

await Task.Run(() => Serializer.SerializeWithLengthPrefix(
    stream, data, PrefixStyle.Base128), cancellationToken); 

Alternativamente, se puede utilizar una bastante simple método de ayuda ripped from my JuiceStream library que he presentado como parte de async feature request to protobuf-net:

await ProtobufEx.SerializeWithLengthPrefixAsync(
    stream, data, PrefixStyle.Base128, cancellationToken); 
await ProtobufEx.DeserializeWithLengthPrefixAsync<MyType>(
    stream, PrefixStyle.Base128, cancellationToken); 
+0

Aunque no es el enfoque más ideal, es una buena alternativa. – tunafish24

2

estoy usando protobuff sobre el red. Mientras que la siguiente solución no garantiza que el bloque de costumbre, que hace la vida mucho mejor:

byte[] emptyByteArray = new Byte[0]; 
await stream.ReadAsync(emptyByteArray, 0, 0); 
TaskData d = Serializer.DeserializeWithLengthPrefix<TaskData>(stream, PrefixStyle.Base128); 

Debido a que nos aseguramos de que no hay datos reales de la corriente antes de empezar a deserializar, sólo terminará cuando el bloqueo la secuencia contiene un mensaje parcial.

Editar: Y podemos usar un truco similar para la serialización:

MemoryStream mstm = new MemoryStream(); 
Serializer.SerializeWithLengthPrefix(mstm, data, PrefixStyle.Base128); 
await stream.WriteAsync(mstm.GetBuffer(), 0, (int)mstm.Position); 

Como beneficio adicional, éste no garantiza que nunca se bloquee.

Cuestiones relacionadas