异步protobuf序列化

时间:2012-06-25 10:19:00

标签: c# .net protobuf-net

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

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

3 个答案:

答案 0 :(得分:5)

不,目前不支持,并且很多工作。

我的建议是:使用异步API自己缓冲数据,然后拥有数据时,使用像MemoryStream这样的反序列化......

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

答案 1 :(得分:2)

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

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

或者,您可以使用我作为ripped from my JuiceStream library的一部分提交的相当简单的帮助方法async feature request to protobuf-net

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

答案 2 :(得分:2)

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

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

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

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

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

作为奖励,这个确实绝不会阻止。