异步protobuf序列化

protobuf-net实现的一个限制是它同步调用底层流。 通过不提供异步API,例如BeginSerialize / EndSerialize或TPL等价物,我们被迫绑定一个等待同步流I / O的线程。

有没有计划在protobuf-net中提供异步方法,或者有任何创造性的方法来解决这个问题?

不,这目前不受支持,并且会做很多工作。

我的建议是:使用异步API自己缓冲数据,然后获得数据时,使用类似MemoryStream来反序列化…

在我的辩护中,我不知道在这里提供异步API的任何其他序列化程序。 特别是,在谈论慢/异步流时,这通常意味着“网络”:你通常会在那里考虑“框架”的问题; protobuf-net不会知道您的框架要求……

您可以等待将在线程池中运行同步代码的Task.Run 。 它不是最有效的解决方案,但它比阻止更好。 您甚至可以将自己的CancellationToken提交给Task.Run

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

或者,您可以使用从我的JuiceStream库中提取的一个非常简单的帮助方法,该方法已作为异步function请求的一部分提交给protobuf-net :

 await ProtobufEx.SerializeWithLengthPrefixAsync( stream, data, PrefixStyle.Base128, cancellationToken); await ProtobufEx.DeserializeWithLengthPrefixAsync( stream, PrefixStyle.Base128, cancellationToken); 

我在网络上使用protobuff。 虽然以下解决方案并不能保证它不会阻塞,但它确实让生活变得更好:

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

因为我们在开始反序列化之前确保流上有实际数据,所以只有当流包含部分消息时才会阻塞。

编辑:我们可以使用类似的技巧进行序列化:

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

作为奖励,这个确保永远不会阻止。