尝试同时反序列化多个对象

时间:2012-12-09 13:18:49

标签: c# serialization

我试图将一些对象从服务器发送到客户端。 我的问题是,当我只发送1个对象时,一切正常。但是目前我添加了另一个对象,抛出异常 - “二进制流不包含有效的二进制头”或“没有对象的映射(随机数)”。 我的想法是,反序列化不了解流的开始/结束位置,我希望你们可以帮助我。

继承我的反序列化代码:

public void Listen()
        {
            try
            {
                bool offline = true;
                Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
                    new Action(() => offline = Offline));
                while (!offline)
                {
                    TcpObject tcpObject = new TcpObject();
                    IFormatter formatter = new BinaryFormatter();
                    tcpObject = (TcpObject)formatter.Deserialize(serverStream);

                    if (tcpObject.Command == Command.Transfer)
                    {
                        SentAntenna sentAntenna = (SentAntenna)tcpObject.Object;

                        int idx = 0;
                        foreach (string name in SharedProperties.AntennaNames)
                        {
                            if (name == sentAntenna.Name)
                                break;
                            idx++;
                        }

                        if (idx < 9)
                        {
                            PointCollection pointCollection = new PointCollection();
                            foreach (Frequency f in sentAntenna.Frequencies)
                                pointCollection.Add(new Point(f.Channel, f.Intensity));

                            SharedProperties.AntennaPoints[idx] = pointCollection;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message); // raise an event
            }
        }

序列化代码:

case Command.Transfer:
                            Console.WriteLine("Transfering");
                            Thread transfer = new Thread(new ThreadStart(delegate
                            {
                                try
                                {
                                    string aName = tcpObject.Object.ToString();
                                    int indx = 0;
                                    foreach (string name in names)
                                    {
                                        if (name == aName)
                                            break;
                                        indx++;
                                    }

                                    if (indx < 9)
                                    {
                                        while (true) // need to kill when the father thread terminates
                                        {
                                            if (antennas[indx].Frequencies != null)
                                            {
                                                lock (antennas[indx].Frequencies)
                                                {
                                                    TcpObject sendTcpObject = new TcpObject();
                                                    sendTcpObject.Command = Command.Transfer;
                                                    SentAntenna sa = new SentAntenna(antennas[indx].Frequencies, aName);
                                                    sendTcpObject.Object = sa;
                                                    formatter.Serialize(networkStream, sendTcpObject);
                                                }
                                            }
                                        }
                                    }
                                }
                                catch (Exception ex) { Console.WriteLine(ex); }
                            }));
                            transfer.Start();
                            break;

2 个答案:

答案 0 :(得分:0)

有趣。您的序列化代码中没有什么特别奇怪的东西,我曾经看过人们过去使用vanilla concatenation处理多个对象,虽然我实际上总是建议不要这样,因为BinaryFormatter没有明确声明这种情况没问题。但是:如果不是,我唯一可以建议的是实施自己的框架;所以你的写代码变成:

  • 序列化为空的MemoryStream
  • 记下长度并将长度写入NetworkStream,例如作为一个简单的固定宽度32位网络字节顺序整数
  • 将有效负载从MemoryStream写入NetworkStream
  • 冲洗,重复

读取的代码变为:

  • 准确读取4个字节并计算长度
  • 缓冲许多字节到MemoryStream
  • 从NetworkStream反序列化

(在两种情况下都注意到在写入和读取之间将MemoryStream的位置设置为0)

如果你想在读取时避免使用缓冲区,你也可以实现一个封闭长度的Stream子类,这个位更复杂。

答案 1 :(得分:0)

显然我提出了一个非常简单的解决方案。我确保只允许一个线程同时传输数据,所以我更改了这行代码:

formatter.Serialize(networkStream, sendTcpObject);

到这些代码行:

if (!transfering) // making sure only 1 thread is transfering data
{
    transfering = true;
    formatter.Serialize(networkStream, sendTcpObject);
    transfering = false;
}