2016-03-30 2 views
3

Я пишу проект для передачи объекта из родительского приложения в дочернее приложение. Я использую Protobuf для сериализации и десериализации данных. Я также использую Non-Persisted Memory-Mapped File для записи в процессе сериализации (и чтения с десериализации). Вот код:IPC Использование файлов Protobuf и Memory Mapped C#

[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 называется):

Exception брошенного: 'ProtoBuf.ProtoException' в Protobuf-net.dll Дополнительная информация: Недопустимое поле в исходных данных: 0 Я думаю, что эта ошибка возникает, потому что поток больше, чем фактические данные, которые он содержит. Когда поток десериализуется, я думаю, что он начинает читать за пределами фактических данных.

Исключение брошено: «ProtoBuf.ProtoException» в Protobuf-net.dll Дополнительная информация: Нет конструктор без параметров не найдено для испытаний

Я не уверен, что лучший способ, чтобы исправить это, однако. Есть ли способ прочитать байты из потока, пока не осталось данных, а затем остановится? Если нет, я могу решить этот другой путь?

+0

Дикое предположение, может быть, потому что свойства 'set' являются частными? Использование атрибутов может указывать на то, что используется отражение. –

+0

Я пробовал это только для того, чтобы быть в безопасности, но эта же ошибка бросается. Я почти уверен, что Protobuf просто вызывает конструктор, поэтому это не должно быть проблемой. – user2481095

+0

На самом деле я только что кое-что обнаружил. У меня также был конструктор по умолчанию public Test() {}. Когда я удалил это, вызывается новое исключение: Исключение выбрано: «ProtoBuf.ProtoException» в protobuf-net.dll Дополнительная информация: для Test не найдено конструктора без параметров. Таким образом, кажется, что поток, получающий Deserialize, пуст ? Не знаю, почему это произойдет. – user2481095

ответ

3

Я не уверен, что лучший способ это исправить

  1. добавить конструктор без параметров (это может быть private, если вам нравится), или
  2. добавить SkipConstructor = true в качестве параметров от [ProtoContract(...)] от типа

однако. Есть ли способ прочитать байты из потока, пока не осталось данных, а затем остановится?

Да, это значение по умолчанию в буферах протоколов, так как внешнее сообщение не содержит маркер длины или конечный маркер (он предназначен для добавления). Тем не менее, в вашем случае, это, вероятно, не то, что вы хотите, так как будет различный мусор (возможно, все нули, возможно, нет) после данных, которые вы сериализуете. Вместо этого вы можете использовать SerializeWithLengthPrefix и DeserializeWithLengthPrefix. И если ваши данные всего 1000 байт, MemoryStream будет в порядке - не нужно использовать неуправляемую память.

+0

Я отредактировал код, чтобы отразить ваши изменения. Эта последняя часть о неуправляемой памяти. Вы говорите, что в моем случае я должен просто использовать MemoryStream вместо MemoryMappedFile? – user2481095

+0

@ user2481095 Я не знаю достаточно о вашем конкретном случае использования, чтобы сказать, что с уверенностью, однако, я бы не * прыгнул * на использование неуправляемой памяти. Если есть веская причина: отлично –

Смежные вопросы