Protrobuf - 错误:检查元数据时超时

时间:2013-05-10 14:11:39

标签: .net wcf silverlight-5.0 protobuf-net

我收到以下异常

检查元数据时超时;这可能表示死锁。通常可以通过在应用程序初始化期间准备必要的序列化程序来避免这种情况,而不是允许多个线程执行初始元数据检查;另请参阅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实现的正确方法吗?

1 个答案:

答案 0 :(得分: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下载(即项目中的“Manage NuGet Packages ...”),选择2.0.0.621,自动选择Silverlight构建。

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

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

我不知道是否的情况,但 如果 问题是你有一个非常复杂的模型(也许也在加载大量外部程序集),然后另一个选项可能是预生成序列化程序集。这意味着您可以将所有反射分析,思考,IL发射等预先移动到构建时(而不是运行时),生成可以引用的dll。这是described here,基本上你只需生成序列化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是您所谓的生成类型。