protobuf-net实现的一个限制是它同步调用底层流。不提供异步API,例如BeginSerialize / EndSerialize或TPL等价物,我们被迫绑定一个等待同步流I / O的线程。
是否有任何计划在protobuf-net中提供异步方法,或者是否有任何创造性的解决此问题的方法?
答案 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);
作为奖励,这个确实绝不会阻止。