[英]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.