C# C-Windows窗体通过使用计时器循环进行tcp侦听而保持冻结状态

C# C-Windows窗体通过使用计时器循环进行tcp侦听而保持冻结状态,c#,timer,infinite-loop,C#,Timer,Infinite Loop,这显然会冻结windows窗体。我正在创建一个TCPListener来与游戏进行通信,并将其回音到游戏机中。它在两侧都可以工作,但windows窗体在此过程中会冻结。计时器间隔为100ms 这里的注释行就是冻结的地方 private void timer2_Tick(object sender, EventArgs e) { // Perform a blocking call to accept requests. // You could also

这显然会冻结windows窗体。我正在创建一个TCPListener来与游戏进行通信,并将其回音到游戏机中。它在两侧都可以工作,但windows窗体在此过程中会冻结。计时器间隔为100ms

这里的注释行就是冻结的地方

private void timer2_Tick(object sender, EventArgs e)
    {
        // Perform a blocking call to accept requests. 
        // You could also user server.AcceptSocket() here.
        TCPString.addData("Connected a client...");
        if (client == null)
        {
            client = listener.AcceptTcpClient();
            if (client == null)
                return;
        }
        data = null;
        sentData = null;
        sentData = "Hallo";
        // Get a stream object for reading and writing
        NetworkStream stream = client.GetStream();

        int i;

        if ((i = stream.Read(bytes, 0, bytes.Length)) != 0) //"here"
        {
            // Translate data bytes to a ASCII string.
            data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
            TCPString.addData("Received: " + data.ToString());

            // Process the data sent by the client.
            data = data.ToUpper();

            if (client.ReceiveTimeout > 5000)
            {
                client.Close();
                client = null;
                return;
            }

            byte[] msg = System.Text.Encoding.ASCII.GetBytes(sentData);

            // Send back a response.
            stream.Write(msg, 0, msg.Length);
            TCPString.addData("Sent: " + data.ToString());
        }
        else
        {
            sentData = "Go away";
            byte[] msg = System.Text.Encoding.ASCII.GetBytes(sentData);
            stream.Write(msg, 0, msg.Length);
            client.Close();
        }
    }

简短版本:你做错了tm。UI冻结是因为您正在使用System.Windows.Forms.Timer,这会在UI线程上引发勾号事件。调用Stream.Read会阻塞线程,直到一些数据到达,从而导致中断。你可以使用不同的计时器,但事实是你根本不应该使用计时器。相反,使用异步API:调用TcpListener.AcceptTcpClientAsync,完成后获取一次NetworkStream,并在该对象上使用ReadAsync和WriteAsync方法。从异步方法调用这些方法,并等待它们。如果您包括清楚说明您的场景的方法,则可以提供一个具体的答案,说明如何正确使用异步API。对于编程GUI软件,GUI作为主线程运行,要在不影响GUI性能的情况下执行繁重的操作,您需要在另一个线程中异步执行。