IPC 使用 Protobuf 和内存映射文件 C#
IPC Using Protobuf and Memory Mapped Files C#
我正在编写一个项目以将对象从父应用程序传递到子应用程序。我正在使用 Protobuf 序列化和反序列化数据。我还使用非持久内存映射文件在序列化时写入(并在反序列化时读取)。这是代码:
[ProtoContract(SkipConstructor = true)]
public class Test
{
[ProtoMember(1)]
public int ID { get; private set; }
[ProtoMember(2)]
public bool TestBool { get; private set; }
[ProtoMember(3)]
public string MessageBody { get; private set; }
public Test(int id, bool testBool, string messageBody)
{
this.ID = id;
this.TestBool = testBool;
this.MessageBody = messageBody;
}
public void Serialize()
{
MemoryMappedFile mmf = MemoryMappedFile.CreateNew("testmap", 1000);
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
Serializer.SerializeWithLengthPrefix(stream, this, PrefixStyle.Base128);
stream.Flush();
}
}
public static Test Deserialize()
{
using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("testmap"))
{
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
return Serializer.DeserializeWithLengthPrefix<Test>(stream, PrefixStyle.Base128);
}
}
}
}
//On the parent application
var msg = new SharedLibrary.Test(1234, true, "Test message hahah");
msg.Serialize();
//spawn child application
//On the child application
Test result = Test.Deserialize();
当我 运行 此代码时出现以下错误(当调用 Serializer.Deserialize 时):
抛出异常:'ProtoBuf.ProtoException' in protobuf-net.dll
附加信息:源数据中的无效字段:0
我认为发生此错误是因为流大于它包含的实际数据。当流被反序列化时,我认为它开始读取超出实际数据的内容。
抛出异常:'ProtoBuf.ProtoException' in protobuf-net.dll
附加信息:未找到 Test
的无参数构造函数
不过,我不确定解决此问题的最佳方法。有没有办法从流中读取字节直到没有数据,然后停止?如果不能,我可以用另一种方式解决吗?
I'm not sure the best way to fix this
- 添加一个无参数的构造函数(如果你愿意,可以是
private
),或者
- 将
SkipConstructor = true
作为参数添加到您的类型 [ProtoContract(...)]
上
however. Is there a way to read the bytes from a stream until the is no data left and then stop?
是的,这是协议缓冲区中的默认设置,因为最外层的消息不包含长度标记或结束标记(它被设计为可追加的)。但是,在你的情况下,这可能不是你想要的,因为会有各种垃圾(可能全为零,可能不是)after 你序列化的数据。您可能想改用 SerializeWithLengthPrefix
和 DeserializeWithLengthPrefix
。如果您的数据只有 1000 字节,MemoryStream
就可以了——无需使用非托管内存。
我正在编写一个项目以将对象从父应用程序传递到子应用程序。我正在使用 Protobuf 序列化和反序列化数据。我还使用非持久内存映射文件在序列化时写入(并在反序列化时读取)。这是代码:
[ProtoContract(SkipConstructor = true)]
public class Test
{
[ProtoMember(1)]
public int ID { get; private set; }
[ProtoMember(2)]
public bool TestBool { get; private set; }
[ProtoMember(3)]
public string MessageBody { get; private set; }
public Test(int id, bool testBool, string messageBody)
{
this.ID = id;
this.TestBool = testBool;
this.MessageBody = messageBody;
}
public void Serialize()
{
MemoryMappedFile mmf = MemoryMappedFile.CreateNew("testmap", 1000);
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
Serializer.SerializeWithLengthPrefix(stream, this, PrefixStyle.Base128);
stream.Flush();
}
}
public static Test Deserialize()
{
using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("testmap"))
{
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
return Serializer.DeserializeWithLengthPrefix<Test>(stream, PrefixStyle.Base128);
}
}
}
}
//On the parent application
var msg = new SharedLibrary.Test(1234, true, "Test message hahah");
msg.Serialize();
//spawn child application
//On the child application
Test result = Test.Deserialize();
当我 运行 此代码时出现以下错误(当调用 Serializer.Deserialize 时):
抛出异常:'ProtoBuf.ProtoException' in protobuf-net.dll
附加信息:源数据中的无效字段:0
我认为发生此错误是因为流大于它包含的实际数据。当流被反序列化时,我认为它开始读取超出实际数据的内容。
抛出异常:'ProtoBuf.ProtoException' in protobuf-net.dll 附加信息:未找到 Test
的无参数构造函数不过,我不确定解决此问题的最佳方法。有没有办法从流中读取字节直到没有数据,然后停止?如果不能,我可以用另一种方式解决吗?
I'm not sure the best way to fix this
- 添加一个无参数的构造函数(如果你愿意,可以是
private
),或者 - 将
SkipConstructor = true
作为参数添加到您的类型[ProtoContract(...)]
上
however. Is there a way to read the bytes from a stream until the is no data left and then stop?
是的,这是协议缓冲区中的默认设置,因为最外层的消息不包含长度标记或结束标记(它被设计为可追加的)。但是,在你的情况下,这可能不是你想要的,因为会有各种垃圾(可能全为零,可能不是)after 你序列化的数据。您可能想改用 SerializeWithLengthPrefix
和 DeserializeWithLengthPrefix
。如果您的数据只有 1000 字节,MemoryStream
就可以了——无需使用非托管内存。