この関数class Simulator
では、クライアント側で逆シリアル化を試みます:
private void OnHandshakeSimulationStart(Peer peer, Message msg, int seq)
{
System.Diagnostics.Trace.WriteLine("TRY OnHandshakeSimulationStart id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
try
{
HandshakeSimulationStart simstart = msg as HandshakeSimulationStart;
if (simstart == null) OnHandshakeFailed();
System.Diagnostics.Trace.WriteLine("#1.1 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
//Simulator sim = (Simulator)simstart.SimulationState.GetObject();
Simulator sim = null;
System.Diagnostics.Trace.WriteLine("#1.2 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
try
{
// sim = (Simulator)simstart.SimulationState.GetObject();
using (MemoryStream ms = (MemoryStream)simstart.SimulationState.GetObjectWoDeserialize())
{
System.Diagnostics.Trace.WriteLine("#2.1 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
ms.Seek(0, SeekOrigin.Begin);
System.Diagnostics.Trace.WriteLine("#2.2 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
sim = Serializer.Deserialize<Simulator>(ms); //(Simulator)new BinaryFormatter().Deserialize(ms);
System.Diagnostics.Trace.WriteLine("#2.3 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
}
catch (SerializationException e)
{
Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
}
System.Diagnostics.Trace.WriteLine("#3 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
sim.PostDeserialize();
System.Diagnostics.Trace.WriteLine("#4 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
lock (this)
{
simulator = sim;
// команды полученные до этого ставим в очередь
foreach (Commands.Command cmd in CollectedCommandsDuringHandshake)
if (cmd.tact >= simulator.tactCounter)
simulator.InternalQueue(cmd);
System.Diagnostics.Trace.WriteLine("#5 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
CollectedCommandsDuringHandshake = null;
// настраиваем сетевое время
networkTime = new Network.Timer(simulator.HZ);
// настраиваем обработчик команд
simulator.OnAfterCommand.Add(typeof(Commands.Command), new CommandHandler(OnAfterCommand));
System.Diagnostics.Trace.WriteLine("#6 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
// хендшейк закончен
OnHandshakeCompleted();
System.Diagnostics.Trace.WriteLine("#7 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
CurrentReceiveHandler = new Peer.MessageReceivedHandler(OnMessageReceivedInActiveState);
System.Diagnostics.Trace.WriteLine("#8 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
}
catch (Exception exception)
{
System.Diagnostics.Trace.WriteLine("OnHandshakeSimulationStart ERROR: " + exception.Message + " id = " + +System.Threading.Thread.CurrentThread.ManagedThreadId);
}
}
DebugView.exe アプリケーションを使用すると、次のようになります。
[26480] Client handshaked: id=0 name=ECDIS[1] version=3.8.1
[26480] ObjectWrapper(object obj) - ms.Length = 67 id = 10
[26480] Write(Network.Packet packet) - ObjectDumpProtoBuf.Length = 256 id = 10
[25404] ObjectWrapper(Network.Packet packet) - len = 256 id = 5
[25404] TRY OnHandshakeSimulationStart id = 5
[25404] #1.1 id = 5
[25404] #1.2 id = 5
[25404] GetObjectWoDeserialize() id = 5
[25404] #2.1 id = 5
[25404] #2.2 id = 5
[25404] OnHandshakeSimulationStart ERROR: Invalid field in source data: 0 id = 5
逆シリアル化中に例外が発生したことがわかりましたclass Simulator
。
namespace Trainer
{
[Serializable]
[ProtoContract]
public class Simulator
{
[ProtoMember(1)]
public IDictionary<int, Task> tasks = new Dictionary<int, Task>();
[ProtoMember(2)]
public Workplace[] workplaces;
[ProtoMember(3)]
public int tactCounter = 0;
[ProtoMember(4)]
public int tactLimit = 0;
[NonSerialized]
public int sheduleLimit = 0;
[ProtoMember(5)]
public int HZ = 100;
public int SyncFactor { get { return 1; } } // HZ/8
public double DT { get { return 1.0 / (double)HZ; } }
[ProtoMember(6)]
List<Commands.Command> commandQueue = new List<Commands.Command>();
//Queue commandQueue = new Queue();
[NonSerialized]
public CommandEventTable OnBeforeCommand = new CommandEventTable();
[NonSerialized]
public CommandEventTable OnAfterCommand = new CommandEventTable();
public void PostDeserialize()
{
OnBeforeCommand = new CommandEventTable();
OnAfterCommand = new CommandEventTable();
foreach (Task t in tasks.Values)
t.PostDeserialize();
}
public Simulator()
{
}
//there are also a lot of functions...
}
オブジェクトラッパーはシリアル化/逆シリアル化に役立ち、binaryformatter で正常に動作しますが、protobuf-net を使用するように変更します。
namespace Trainer.Network
{
[Serializable]
[ProtoContract]
public class ObjectWrapper : IFile
{
//public byte[] ObjectDump;
[ProtoMember(1)]
public byte[] ObjectDumpProtoBuf;
public ObjectWrapper(object obj)
{
using (MemoryStream ms = new MemoryStream())
{
//for protobuf-net:
Serializer.Serialize(ms, obj);
ObjectDumpProtoBuf = ms.GetBuffer();
//for binaryformatter:
//new BinaryFormatter().Serialize(ms,obj);
//ObjectDump = ms.GetBuffer();
_Guid = Guid.NewGuid();
System.Diagnostics.Trace.WriteLine("ObjectWrapper(object obj) - ms.Length = " + ms.Length + " id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
}
public ObjectWrapper(Network.Packet packet)
{
bool body = packet.ReadBool();
if (body)
{
int len = packet.ReadInt();
ObjectDumpProtoBuf = (byte[])packet.Read(typeof(byte), len);
//ObjectDump = (byte[])packet.Read(typeof(byte),len);
System.Diagnostics.Trace.WriteLine("ObjectWrapper(Network.Packet packet) - len = " + len + " id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
else
_Guid = (Guid)packet.Read(typeof(Guid));
}
public void Write(Network.Packet packet)
{
System.Diagnostics.Trace.WriteLine("Write(Network.Packet packet) - ObjectDumpProtoBuf.Length = " + ObjectDumpProtoBuf.Length + " id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
packet.Write(true);
//packet.Write((int)ObjectDump.Length);
//packet.Write(ObjectDump);
packet.Write((int)ObjectDumpProtoBuf.Length);
packet.Write(ObjectDumpProtoBuf);
}
public void WriteFileRef(Network.Packet packet)
{
packet.Write(false);
packet.Write(Guid);
}
public object GetObject()
{
//using (MemoryStream ms = new MemoryStream(ObjectDump))
using (MemoryStream ms = new MemoryStream(ObjectDumpProtoBuf))
return new BinaryFormatter().Deserialize(ms);
}
public MemoryStream GetObjectWoDeserialize()
{
System.Diagnostics.Trace.WriteLine("GetObjectWoDeserialize() id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
return new MemoryStream(ObjectDumpProtoBuf);
}
#region IFile Members
[ProtoMember(2)]
public Guid _Guid = new Guid();
public Guid Guid { get { return _Guid; } }
public byte[] Data
{
//get { return ObjectDump; }
//set { ObjectDump = value;}
get { return ObjectDumpProtoBuf; }
set { ObjectDumpProtoBuf = value; }
}
#endregion
}
}
質問:問題の正確な場所を特定するにはどうすればよいですか? 「ソース データの無効なフィールド: 0」という意味です ソース データ 0 とは何ですか? これは
[ProtoMember(1)]
public IDictionary<int, Task> tasks = new Dictionary<int, Task>();
か否か?だから私は何が間違っているのか理解できません...