2

我收到以下异常

"检查元数据时超时;这可能表示死锁。这通常可以通过在应用程序初始化期间准备必要的序列化程序来避免,而不是允许多个线程执行初始元数据检查;另请参阅 LockContended 事件 (System.String) "

尝试使用 protobuf.net 序列化/反序列化对象时。我将 protobuf.net 用于 Silverlight 和 WCF 服务。在 WCF 服务上序列化结果并在客户端(Silverlight)端反序列化相同的响应。

我为此使用了扩展方法。这是代码

 public static byte[] GetSerializeByteArray<T>( this T entity )
    {
          using ( var stream = new MemoryStream() )
            {
                Serializer.Serialize( stream, entity );
                return stream.ToArray();
            }
    }

  public static T DeserializeByteArray<T>( this byte[] byteArray )
    {
        if ( byteArray == null )
        {
            throw new ArgumentNullException( "byteArray" );
        }
        try
        {
            using ( Stream result = new MemoryStream( byteArray ) )
            {
                return Serializer.Deserialize<T>( result );
            }
        }
        catch ( Exception )
        {
            throw new InvalidOperationException( "Invalid Type" );
        }
    }

这是我们的模型类,它驻留在其他项目(可移植类库)上,并在客户端(Silverlight)和服务器(WCF)端都使用。

 [ProtoContract]
public class Class1
{
    [ProtoMember( 1 )]
    public string Name       
 }

我不明白为什么这个异常一次又一次地发生!您能否向我解释一下,这是使用 protobuf-net 实现的正确方法吗?

4

1 回答 1

1

我已经使用您问题中的代码创建了一个测试装置,带有一个简单的按钮等 - 以下工作正常:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var obj = new Class1 { Name = "abc" };
        var raw = obj.GetSerializeByteArray();
        var clone = raw.DeserializeByteArray<Class1>();
        ((Button)sender).Content = clone.Name;
    }

即按钮的文本设置为"abc",我们序列化和反序列化的值。对于这个测试,我使用的是 NuGet 下载(即项目中的“管理 NuGet 包...”),它选择了 2.0.0.621,自动选择了 Silverlight 构建。

没有遇到任何问题。可能性:

  • 你也许使用不同的dll?也许是可移植类库 (PCL) 版本?这不会是错误的,因为 PCL 版本应该可以在 Silverlight 上运行 - 我只是想找到一个解释,为什么我无法重现您所看到的内容。例如,理论上可能存在我需要调查的 PCL 版本中的错误。
  • 你的实际模型要复杂得多吗?您可能会看RuntimeTypeModel.Default.MetadataTimeoutMilliseconds- 这应该默认为 5 秒,这在任何正常情况下都是很长的时间 - 知道增加它是否使它工作,或者是否某些代码已经将它更改为一个更小的值会很有趣

我不知道不是这样,但是如果问题是您有一个非常复杂的模型(可能还加载了大量外部程序集),那么另一种选择可能是预先生成序列化程序集. 这意味着您可以将所有反射分析、思考、IL 发射等提前移动到构建时(而不是运行时),生成您可以引用的 dll。这在此处进行了描述,基本上您只需生成序列化 dll,从您的 silverligh 项目中引用它,然后将该代码替换为:

public static byte[] GetSerializeByteArray<T>(this T entity)
{
    using (var stream = new MemoryStream())
    {
        new MyCustomSerializer().Serialize(stream, entity);
        return stream.ToArray();
    }
}

public static T DeserializeByteArray<T>(this byte[] byteArray)
{
    if (byteArray == null)
    {
        throw new ArgumentNullException("byteArray");
    }
    try
    {
        using (Stream result = new MemoryStream(byteArray))
        {
            return (T)(new MyCustomSerializer().Deserialize(result, null, typeof(T)));
        }
    }
    catch (Exception)
    {
        throw new InvalidOperationException("Invalid Type");
    }
}

MyCustomSerializer你所说的生成类型在哪里。

于 2013-05-13T12:57:00.073 回答