Protobuf.net “一旦生成了序列化程序,就无法更改类型”

Posted

技术标签:

【中文标题】Protobuf.net “一旦生成了序列化程序,就无法更改类型”【英文标题】:Protobuf.net "The type cannot be changed once a serializer has been generated" 【发布时间】:2010-10-23 22:00:14 【问题描述】:

我有一些使用 Protobuf.net 的相当简单的代码,它抛出了一个非常奇怪的异常。 在第 167 行的 MetaType.cs 中,它会引发 InvalidOperationException “一旦生成序列化程序,就无法更改类型”。这是什么意思,我该如何解决?

我的代码如下所示:

这个方法开始所有的序列化:

while (!Parallel.For(0, 100, (i) =>

    Widget w;
    lock (f)  w = f.CreateWidget(); 

    SerialiseWidget(w);

).IsCompleted)

    Thread.Sleep(10);

非常简单,它只是并行遍历所有内容,并序列化 100 个小部件。

serialise方法也很简单:

private byte[] SerialiseWidget(Widget w)

    using (MemoryStream m = new MemoryStream())
    
        Serializer.Serialize<PacketChunk>(m, w);

        return m.ToArray();
    

最后,小部件类如下所示:

[ProtoContract]
private class Widget

    [ProtoMember(1)]
    public int a;

    [ProtoMember(2)]
    public byte[] b;

    [ProtoMember(3)]
    public Thing c; //Thing is itself a protocontract

    [ProtoMember(4)]
    public int d;

    [ProtoMember(5)]
    public int e;

编辑:: 我怀疑这可能与我并行循环的事实有关。 Protobuf.net 对于这种事情的线程安全性如何?

【问题讨论】:

【参考方案1】:

Protobuf.net 对于这类事情的线程安全性如何?

嗯,它注意到发生了一些奇怪的事情:)

只需在主题前的某个时间点添加对 Serializer.PrepareSerializer 的调用(应用程序启动是显而易见的点),它应该会原谅你...

编辑:想一想,我可以做一个相当简单的改变来帮助这个特定的场景;当我有机会时,我会调整它。此外,这只会影响未发布“v2”代码(来自源代码)——预构建的 dll 不受此 AFAIK 的影响。

【讨论】:

非常好,调用 PrepareSerializer 方法有效。感谢马克的快速反应:D

以上是关于Protobuf.net “一旦生成了序列化程序,就无法更改类型”的主要内容,如果未能解决你的问题,请参考以下文章

Protobuf.net 内存使用情况

Protobuf.net 异常 - 检查元数据时超时

ProtoBuf.Net - 使用 Proto 作为 TypeFormatter

protobuf.net 处理 Nullable<DateTimeOffset>

protobuf.net 和条件序列化

列表的 Protobuf.net 对象图序列化