簡體   English   中英

GUI 在 c# 套接字中凍結

[英]GUI freezes in c# socket

我使用套接字編程在 c# 中制作了一個文件接收服務器。 我做了一個 GUI 。 有一個名為“connect”的按鈕,單擊它會啟動服務器,還有一個文本框,當服務器啟動時會顯示一條消息。 但是當我單擊按鈕時,GUI 會凍結。

這是我的示例代碼:

using System;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections.Generic;

class sampleserver : Form
{

    private TextBox newText;
    public TcpClient tcpClient;
    public TcpListener tcpListener;
    public sampleserver()
{
    Text = " TCP Server";
    Size = new Size(400, 380);        
    newText = new TextBox();
    newText.Parent = this;
    newText.Size = new Size(200, 2 * Font.Height);
    newText.Location = new Point(10, 55);

    Button connect = new Button();
    connect.Parent = this;
    connect.Text = "Connect";
    connect.Location = new Point(295, 20);
    connect.Size = new Size(6 * Font.Height, 2 * Font.Height);
    connect.Click += new EventHandler(ButtonConnectOnClick);        

}


void ButtonConnectOnClick(object obj, EventArgs ea)
{
    tcpListener = new TcpListener(IPAddress.Any, 1234);
    tcpListener.Start();
    newText.Text = "Server started"; //**This line is not working**

    //Infinite loop to connect to new clients      
    while (true)
    {
        // Accept a TcpClient      
        TcpClient tcpClient = tcpListener.AcceptTcpClient();
        string address = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address.ToString();

                   byte[] data = new byte[1024];
        NetworkStream ns = tcpClient.GetStream();
        int recv = ns.Read(data, 0, data.Length);
                    StreamReader reader = new StreamReader(tcpClient.GetStream());

        // The first message from the client is the file size      
        string cmdFileSize = reader.ReadLine();


        int length = Convert.ToInt32(cmdFileSize);
        byte[] buffer = new byte[length];
        int received = 0;
        int read = 0;
        int size = 1024;
        int remaining = 0;

        // Read bytes from the client using the length sent from the client      
        while (received < length)
        {
            remaining = length - received;
            if (remaining < size)
            {
                size = remaining;
            }

            read = tcpClient.GetStream().Read(buffer, received, size);
            received += read;
        }

    }

}
public static void Main()
{
    Application.Run(new sampleserver());
}
}

我需要進行哪些更改才能正常運行?

我建議您使用異步套接字,但您也可以只制作該按鈕單擊方法Asynchronous ,就像這樣。

async void ButtonConnectOnClick(object obj, EventArgs ea)
{
tcpListener = new TcpListener(IPAddress.Any, 1234);
tcpListener.Start();
newText.Text = "Server started"; //**This line is not working**
  await Task.Run(() =>
   {
//Infinite loop to connect to new clients      
while (true)
{
    // Accept a TcpClient      
    TcpClient tcpClient = tcpListener.AcceptTcpClient();
    string address = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address.ToString();

               byte[] data = new byte[1024];
    NetworkStream ns = tcpClient.GetStream();
    int recv = ns.Read(data, 0, data.Length);
                StreamReader reader = new StreamReader(tcpClient.GetStream());

    // The first message from the client is the file size      
    string cmdFileSize = reader.ReadLine();


    int length = Convert.ToInt32(cmdFileSize);
    byte[] buffer = new byte[length];
    int received = 0;
    int read = 0;
    int size = 1024;
    int remaining = 0;

    // Read bytes from the client using the length sent from the client      
    while (received < length)
    {
        remaining = length - received;
        if (remaining < size)
        {
            size = remaining;
        }

        read = tcpClient.GetStream().Read(buffer, received, size);
        received += read;
    }

     }

 });
}

這將使整個方法異步,現在您可以在不凍結主 UI 的情況下從套接字讀取。

祝你好運。

UI 事件通常意味着運行然后返回。 您的程序正在啟動應該在線程中啟動的代碼——通過按鈕代碼——然后在應用程序退出時正確停止。

正如 Ron Beyer 所說,你有一段while(true) ,但我更感興趣的是讀取是否超時以及按下按鈕后如何返回主 UI 線程。 看起來您永遠不會返回主 UI 線程。 正如我的評論所述,我會測試網絡代碼,包括控制台應用程序中的 while 循環,然后添加 UI 的復雜性。

順便說一句,正如其他評論所指出的,當您設置此代碼以使網絡設置(啟動)成功時,您不能允許再次單擊啟動按鈕。 您必須禁用(變灰)該按鈕,因此無法雙擊它,並且只有在網絡啟動(啟動)失敗時才啟用。 第二個按鈕,不是灰色的,可以讓你關閉一切。

線程和 UI 並不是您認為的那么簡單。 他們需要相當多的工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM