当连接到服务器并在主窗口中调用方法时,WPF客户端崩溃

rqenqsqc  于 2023-06-24  发布在  其他
关注(0)|答案(1)|浏览(97)

我创建了一个简单的基于TCP的服务器,并有这个ClientHandle脚本。这个问题有点复杂。

public class ClientHandle
    {
        public static event Action OnAddedDevice;
        
        public static void Welcome(Packet packet)
        {
            string msg = packet.ReadString();
            int myId = packet.ReadInt();
            
            Client.instance.myId = myId;
            ClientSend.WeclomeReceived();
        }

        public static void AddDevice(Packet packet)
        {
            int myId = packet.ReadInt();
            
            OnAddedDevice?.Invoke();
        }
    }

并且在启动WPF时订阅OnAddedDevice事件

public NetLogic(MainWindow mainWindow)
        {
            _mainWindow = mainWindow;
            ClientHandle.OnAddedDevice += TestA;
            StartServer();
            Client client = new Client();
            client.ConnectToServer();
        }

我的客户类

public class Client
    {
        public static Client instance;
        public static int dataBufferSize = 4096;

        public string ip = "127.0.0.1";
        public int port = 26950;
        public int myId = 0;
        public TCP tcp;

        private delegate void PacketHandler(Packet _packet);
        private static Dictionary<int, PacketHandler> packetHandlers;

        public Client()
        {
            instance = this;
            tcp = new TCP();
        }

        public void ConnectToServer()
        {
            InitializeClientData();
            tcp.Connect();
        }

        public class TCP
        {
            public TcpClient socket;

            private NetworkStream stream;
            private Packet receivedData;
            private byte[] receiveBuffer;

            public void Connect()
            {
                socket = new TcpClient
                {
                    ReceiveBufferSize = dataBufferSize,
                    SendBufferSize = dataBufferSize
                };

                receiveBuffer = new byte[dataBufferSize];
                socket.BeginConnect(instance.ip, instance.port, ConnectCallback, socket);
            }

            private void ConnectCallback(IAsyncResult _result)
            {
                socket.EndConnect(_result);

                if (!socket.Connected)
                {
                    return;
                }

                stream = socket.GetStream();

                receivedData = new Packet();

                stream.BeginRead(receiveBuffer, 0, dataBufferSize, ReceiveCallback, null);
            }

            public void SendData(Packet _packet)
            {
                try
                {
                    if (socket != null)
                    {
                        stream.BeginWrite(_packet.ToArray(), 0, _packet.Length(), null, null);
                    }
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"Error sending data to server via TCP: {exception}");
                }
            }

            private void ReceiveCallback(IAsyncResult _result)
            {
                try
                {
                    int _byteLength = stream.EndRead(_result);
                    if (_byteLength <= 0)
                    {
                        // TODO: disconnect
                        return;
                    }

                    byte[] _data = new byte[_byteLength];
                    Array.Copy(receiveBuffer, _data, _byteLength);

                    receivedData.Reset(HandleData(_data));
                    stream.BeginRead(receiveBuffer, 0, dataBufferSize, ReceiveCallback, null);
                }
                catch
                {
                    // TODO: disconnect
                }
            }

            private bool HandleData(byte[] _data)
            {
                int _packetLength = 0;
                receivedData.SetBytes(_data);

                if (receivedData.UnreadLength() >= 4)
                {
                    _packetLength = receivedData.ReadInt();
                    if (_packetLength <= 0)
                    {
                        return true;
                    }
                }

                while (_packetLength > 0 && _packetLength <= receivedData.UnreadLength())
                {
                    byte[] _packetBytes = receivedData.ReadBytes(_packetLength);
                    ThreadManager.ExecuteOnMainThread(() =>
                    {
                        using (Packet _packet = new Packet(_packetBytes))
                        {
                            int _packetId = _packet.ReadInt();
                            packetHandlers[_packetId](_packet);
                        }
                    });

                    _packetLength = 0;
                    if (receivedData.UnreadLength() >= 4)
                    {
                        _packetLength = receivedData.ReadInt();
                        if (_packetLength <= 0)
                        {
                            return true;
                        }
                    }
                }

                if (_packetLength <= 1)
                {
                    return true;
                }

                return false;
            }
        }
        
        private void InitializeClientData()
        {
            packetHandlers = new Dictionary<int, PacketHandler>()
            {
                { (int)ServerPackets.welcome, ClientHandle.Welcome },
                { (int)ServerPackets.AddDevice, ClientHandle.AddDevice },
            };
        }
    }

测试A在mainWindow类中有简单的方法调用

public void TestA()
        {
            var mainWindow = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
            mainWindow.GoToPage();
        }

并在服务器启动后10秒内调用AddDevice方法。所以当我调用这个方法时,WPF崩溃,我得到了这些错误enter image description here
非常感谢你的帮助。我将很乐意分享其他需要的信息,以更好地了解问题。
我试着直接调用方法并创建所有的示例,我更改了包信息,所以我只是不知道还有什么可以帮助。

uelo1irk

uelo1irk1#

其实我解决了一个问题我从新线程调用主窗口中的方法。所以我就用了
System. out. println(new Action(MyMethodInMainWindow));

相关问题