winforms 在将我的C#项目拆分为两个独立的项目后,一个项目毫无例外地崩溃了,可能跟不同的线有关?

1hdlvixo  于 2023-08-07  发布在  C#
关注(0)|答案(1)|浏览(86)

我目前正在开发我的第一个C#项目,它是一个聊天室应用程序,使用C# Win Forms和.NET 7.0。用户可以创建一个聊天室并作为服务器,或者只是加入另一个聊天室。对于通信,我使用socket类。
我开始建立一个项目,但现在的要求是有两个独立的项目,可以单独运行。现在我有3个项目在我的解决方案中,一个是合并的,另外两个是客户端和服务器的独立项目。组合解决方案按预期工作,服务器项目也是如此,但客户端项目崩溃而没有抛出异常。这是完全相同的代码,我不明白为什么一个运行良好,而另一个只是关闭。
我想我可以确定导致崩溃的代码行,或者至少这是我在调试器中按F10遍历每一行代码时可以转到的最后一行代码。当我到达这一行并按F10转到下一行时,应用程序关闭。
第一个月
这行代码位于try块中,我没有到达catch块,应用程序只是关闭。第一次遍历while循环和ReceiveAsync()是成功的,而在第二轮while循环中,它在同一行崩溃。但它只在单独的客户端项目中这样做,而不是在完全相同代码的组合项目中。
这行代码位于我写的一个任务中,通过套接字接收消息,这是整个任务,这行代码位于任务的开头。

private async Task ReceiveMessagesAsync()
        {
            Byte[] bytes = new byte[1024];
            while (true)
            {
                if (_clientSocket != null && _clientSocket.Connected)
                {
                    try
                    {
                        //Receive
                        var amountBytes = await _clientSocket.ReceiveAsync(bytes);

                        //If Server closes, we get a nullbyte
                        if (amountBytes == 0)
                        {
                            //UI
                            SetStatusToDisconnected();
                            HideOwnNameLabel();
                            DisplayNotification("Server wurde geschlossen");

                            break;
                        }

                        string decodedMessage = Encoding.UTF8.GetString(bytes, 0, amountBytes);

                        //If we receive a message
                        if (decodedMessage.StartsWith(_messageIdentifyer))
                        {
                            string message = decodedMessage.Substring(_messageIdentifyer.Length);
                            //Prepare the datamodel
                            DataModel? messageModel = JsonSerializer.Deserialize<DataModel>             (message);
  
                            if (messageModel != null)
                            {
                                DisplayMessage(messageModel);
                            }
                        }

                        //If we receive the userlist
                        if (decodedMessage.StartsWith(_listIdentifyer))
                        {
                            _usersDictionary.Clear();

                            //Convert the long string to an Array
                            string[] tempArray = decodedMessage.Split(new[] { _listIdentifyer }, StringSplitOptions.RemoveEmptyEntries);
                            string username = "";
                            int clientID = 0;
                            //we go through the loop with i +=2, since two following array item represent a single user.
                            for (int i = 0; i < tempArray.Length; i += 2)
                            {
                                clientID = Convert.ToInt32(tempArray[i]);
                                username = tempArray[i + 1];
                                //Dont add myself to the userlist
                                if (clientID != _personalId)
                                {
                                    _usersDictionary.Add(clientID, username);
                                }
                            }
                            //UI
                            DisplayOnlineClients();
                            PopulateListBox();
                        }
                    }
                    catch (Exception ex)
                    {

                        Console.WriteLine($"Client [{_personalId}]" + ex.Message);
                        //UI
                        DisplayNotification("Verbindung zum Server verloren");
                        HideOwnNameLabel();
                        SetStatusToDisconnected();
                        break;
                    }
                }
            }
        }

字符串
我是一个初学者,让我解释一下我的思维过程:我使用了一个任务,因为我不希望UI冻结,而我们等待一个消息。Tasks将建议线程池使用任何线程,直到它命中await,并在await结果出现后继续使用任何线程。如果我不使用任务,我的应用程序将冻结,而我等待一个消息。
我不太确定,但我的头脑告诉我,这可能是一个发生在不同线程中的未处理异常,如果这有意义的话?
我试图用这个异常处理程序捕获任何东西:

static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e)
        {
            Exception exception = (Exception)e.ExceptionObject;

            // Log or handle the exception here
            Console.WriteLine("Unhandled Exception:");
            Console.WriteLine(exception.ToString());

        }


但这并没有帮助,应用程序只是关闭,控制台中没有错误消息。
我还发现了一件事:我第一次点击我们谈论的var amountBytes = await _clientSocket.ReceiveAsync(bytes);这一行时,它成功地接收了数据。在此之后,套接字的connected属性将更改为false。我确实读到过这方面的内容,从我所读到的内容来看,connected属性表示套接字的最后一个状态,并且是不可删除的。这让我很困惑,因为我刚刚成功地收到了一些东西,然后它就变成了false。
我在这个问题上坐了好几天了,我在任何地方都找不到解决办法,因为我的问题似乎太特殊了。
我的胃告诉我这与多线程有关,但这可能是错误的,我是一个初学者...
我很感激任何帮助,不管是什么。先谢了。
编辑:我也试图在任务开始时删除if(socket.connected)条件,但没有做任何事情。
Edit 2:一个社区成员询问调用ReceiveMessageAsync()的方法,所以我在这里添加它:

public async Task ConnectAsync(string ipadress)
    {
        _clientForm.NotificationTextbox.Clear();

        try
        {
            //Create endpoint and socket
            _clientEndpoint = new IPEndPoint(IPAddress.Parse(ipadress), _port);
            _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //Connect
            await _clientSocket.ConnectAsync(_clientEndpoint!);

            byte[] tempbytes = new byte[1024];

            //Wait for ID from Server
            var receivedData = await _clientSocket.ReceiveAsync(tempbytes);

            string messageString = Encoding.UTF8.GetString(tempbytes, 0, receivedData);

            //Check if receivedData is indeed the ID
            if (messageString.StartsWith(_IDIdentifyer))
            {

                string[] parts = messageString.Split(new string[] { _IDIdentifyer }, StringSplitOptions.RemoveEmptyEntries);
                _personalId = Convert.ToInt32(parts[0]);
                Console.WriteLine("Client hat ID erhalten:" + _personalId);

                //Send own Nickname to the Server                    
                tempbytes = Encoding.UTF8.GetBytes(_nicknameIdentifyer + _nickname!);
                await _clientSocket.SendAsync(tempbytes);

                //UI
                SetStatusToConnected();
                ConnectButtonLogic();
                DisplayOwnName();

                //Connection established now, received messages get handled in Task ReceiveMessages
                _ = ReceiveMessagesAsync();
            }
            else
            {
                Console.WriteLine("Failed to receive ID");
                //UI
                DisplayNotification("Konnte ID nicht beziehen, versuchen Sie es erneut.");
                SetStatusToDisconnected();
                HideOwnNameLabel();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            //UI
            SetStatusToDisconnected();
            HideOwnNameLabel();
        }
    }


编辑:我找到了解决办法,这是完全不同的东西!
我使用的是win窗体,另一个窗体(主窗体)调用了当前窗体,当新窗体成功打开时,我的代码会被load方法自动执行。我在以前的表单上使用了this.Close(),所以我的新表单在很短的时间后就关闭了,我认为是我的代码导致了这一点。我把这一行改成了this.Hide(),现在可以用了。我想明智的做法是将其更改回this.Close(),并设置应用程序不应该在mainForm关闭时关闭的设置,而是在最后一个Form关闭时关闭。

jq6vz3qz

jq6vz3qz1#

我找到了解决办法,这是完全不同的东西!
我使用的是win窗体,另一个窗体(主窗体)调用了当前窗体,当新窗体成功打开时,我的代码会被load方法自动执行。我在前一个窗体上使用了this.Close(),所以我的新窗体在很短的时间后就关闭了,我认为是我的代码导致了这一点。我把这一行改成了.Hide(),现在它可以工作了。我想如果我把它改回this.Close()并设置应用程序不应该在mainForm关闭时关闭的设置,而是在最后一个Form关闭时关闭的设置,这是明智的。

相关问题