为什么 DataContractSerializer.ReadObject 在 NamedPipeClientStream 上失败/挂起?

问题描述

要传递的简单数据契约类:

[DataContract]
public class MyData
{
    [DataMember]
    public float Value1 {get;set;}
    [DataMember]
    public float Value2 {get;set;}     
    [DataMember]   
    public float Value3 {get;set;}   
}

服务器代码

var serializer = new DataContractSerializer(typeof(MyData));

using (var pipe = new NamedPipeServerStream("testpipe",PipeDirection.InOut))
{
    pipe.WaitForConnection();
    
    var data = new MyData
    {
        Value1 = 200,Value2 = 456,Value3 = 10234.33f
    };

    serializer.WriteObject(pipe,data);
}

客户端代码

var serializer = new DataContractSerializer(typeof(MyData));

using (var client = new NamedPipeClientStream(".","testpipe",PipeDirection.InOut))
{
    client.Connect();
    
    var data = (MyData)serializer.Readobject(client);
}

上面对 Readobject调用只是挂起而不抛出任何异常。 使用 XmlSerializer 是完全一样的。

这些序列化程序甚至可以直接在命名管道流上使用还是被迫使用手动字符串/字节消息解析?

解决方法

您缺少可以在 documentation 中看到的 XmlDictionaryReader。另外请确保不要从同一个项目中运行客户端和服务器类。

我创建了一个控制台项目并运行 server.serialize() 作为主应用程序。

public class Server
{
    public void Serialize()
    {
        using var pipe = new NamedPipeServerStream("testpipe",PipeDirection.InOut);
        var serializer = new DataContractSerializer(typeof(MyData));

        pipe.WaitForConnection();

        var data = new MyData
        {
            Value1 = 200,Value2 = 456,Value3 = 10234.33f
        };

        serializer.WriteObject(pipe,data);
        
    }
}

然后我制作了另一个控制台项目并运行 Client.Deserialize() 作为第二个应用程序(右键单击项目->调试->启动新实例)

public class Client
{
    public void Deserialize()
    {
        using var pipe = new NamedPipeClientStream(".","testpipe",PipeDirection.InOut);
        var reader = XmlDictionaryReader.CreateTextReader(pipe,new XmlDictionaryReaderQuotas());
        var serializer = new DataContractSerializer(typeof(MyData));

        pipe.Connect();

        var data = serializer.ReadObject(reader);
        Console.WriteLine(data);

    }
}

在此设置下效果很好。 我希望这能解决你的问题。 干杯!

Edit1:将答案从使用 FileStream 更改为 NamedPipeStreams 并阐明了我的方法。