2 回答

TA貢獻(xiàn)1859條經(jīng)驗(yàn) 獲得超6個(gè)贊
由于您沒(méi)有在服務(wù)器循環(huán)中訪問(wèn)或更改 UI,我建議使用線程。
您可以像這樣啟動(dòng)新線程:
public Form2()
{
? ? InitializeComponent();
? ? Thread serverThread = new Thread(() => ExecuteServer("test"));
? ? serverThread.Start();
}
不過(guò)這里有幾點(diǎn)需要注意。
首先,永遠(yuǎn)不要在構(gòu)造函數(shù)中啟動(dòng)長(zhǎng)時(shí)間運(yùn)行的線程。Load為此使用該事件。如果雙擊設(shè)計(jì)器中的窗體,則可以為其創(chuàng)建事件處理程序。你也可以這樣做:
public Form2()
{
? ? InitializeComponent();
? ? this.Load += (o, e) => StartServer();
}
private void StartServer()?
{
? ? Thread serverThread = new Thread(() => ExecuteServer("test"));
? ? serverThread.Start();
}
接下來(lái)要注意的是,除了將正確的數(shù)據(jù)發(fā)送到套接字之外,您目前無(wú)法停止線程。您至少應(yīng)該在外部 while 循環(huán)中 使用 avolatile bool而不是 the 。true
你也應(yīng)該Application.Exit盡可能少地使用。對(duì)于這個(gè)線程解決方案,我建議只是跳出 while 循環(huán)并在線程方法結(jié)束時(shí)執(zhí)行一些關(guān)閉操作。你的ExecuteServer-method 看起來(lái)像這樣:
public static void ExecuteServer(string pwd, Action closingAction)
{
? ? // Establish the local endpoint??
? ? // for the socket. Dns.GetHostName?
? ? // returns the name of the host??
? ? // running the application.?
? ? IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
? ? IPAddress ipAddr = ipHost.AddressList[0];
? ? IPEndPoint localEndPoint = new IPEndPoint(ipAddr, 11111);
? ? // Creation TCP/IP Socket using??
? ? // Socket Class Costructor?
? ? Socket listener = new Socket(ipAddr.AddressFamily,
? ? ? ? ? ? ? ? SocketType.Stream, ProtocolType.Tcp);
? ? try
? ? {
? ? ? ? // Using Bind() method we associate a?
? ? ? ? // network address to the Server Socket?
? ? ? ? // All client that will connect to this??
? ? ? ? // Server Socket must know this network?
? ? ? ? // Address?
? ? ? ? listener.Bind(localEndPoint);
? ? ? ? // Using Listen() method we create??
? ? ? ? // the Client list that will want?
? ? ? ? // to connect to Server?
? ? ? ? listener.Listen(10);
? ? ? ? while (_shouldContinue)
? ? ? ? {
? ? ? ? ? ? //Console.WriteLine("Waiting connection ... ");
? ? ? ? ? ? // Suspend while waiting for?
? ? ? ? ? ? // incoming connection Using??
? ? ? ? ? ? // Accept() method the server??
? ? ? ? ? ? // will accept connection of client?
? ? ? ? ? ? Socket clientSocket = listener.Accept();
? ? ? ? ? ? // Data buffer?
? ? ? ? ? ? byte[] bytes = new Byte[1024];
? ? ? ? ? ? string data = null;
? ? ? ? ? ? while (true)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? int numByte = clientSocket.Receive(bytes);
? ? ? ? ? ? ? ? data += Encoding.ASCII.GetString(bytes,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0, numByte);
? ? ? ? ? ? ? ? if (data.IndexOf("<EOF>") > -1)
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? Console.WriteLine("Text received -> {0} ", data);
? ? ? ? ? ? if (data == "<EOF> " + "kill")
? ? ? ? ? ? {
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? else if (data == "<EOF>" + "getpw")
? ? ? ? ? ? {
? ? ? ? ? ? ? ? sendtoclient(clientSocket, pwd);
? ? ? ? ? ? }
? ? ? ? ? ? else
? ? ? ? ? ? {
? ? ? ? ? ? ? ? sendtoclient(clientSocket, "Error 404 message not found!");
? ? ? ? ? ? }
? ? ? ? ? ? // Close client Socket using the?
? ? ? ? ? ? // Close() method. After closing,?
? ? ? ? ? ? // we can use the closed Socket??
? ? ? ? ? ? // for a new Client Connection?
? ? ? ? ? ? clientSocket.Shutdown(SocketShutdown.Both);
? ? ? ? ? ? clientSocket.Close();
? ? ? ? }
? ? }
? ? catch (Exception e)
? ? {
? ? ? ? //Console.WriteLine(e.ToString());
? ? }
? ? closingAction();
}
你StartServer必須稍微調(diào)整一下:
private void StartServer()?
{
? ? Action closingAction = () => this.Close();
? ? Thread serverThread = new Thread(() => ExecuteServer("test", closingAction));
? ? serverThread.Start();
}
一旦服務(wù)器結(jié)束,這將關(guān)閉表單。當(dāng)然,您可以更改執(zhí)行的操作。
布爾值也shouldContinue應(yīng)該是這個(gè)樣子: private static volatile bool _shouldContinue = true;
如果您希望循環(huán)結(jié)束,您當(dāng)然可以將其交換為屬性或任何您想要的,只需將其設(shè)置為 false 即可。
最后一件事,請(qǐng)記住,如果您正在使用阻塞調(diào)用,listener.Accept();您當(dāng)然不會(huì)在更改 bool 時(shí)立即取消線程。對(duì)于這些事情,我建議您遠(yuǎn)離這樣的阻塞調(diào)用,并嘗試查找超時(shí)的事情。
我希望你能以此為起點(diǎn)。
祝你好運(yùn)!
編輯:
在考慮接受的答案時(shí),我必須重申,你永遠(yuǎn)不應(yīng)該在構(gòu)造函數(shù)中啟動(dòng)長(zhǎng)時(shí)間運(yùn)行的線程/任務(wù)。如果你真的想使用 async/await 而不是任務(wù),請(qǐng)不要像接受的答案建議的那樣去做。
首先,將整個(gè)方法體包裹在一個(gè)Task.Run看起來(lái)很糟糕的地方,并帶來(lái)更多的嵌套層。您可以通過(guò)多種方式更好地做到這一點(diǎn):
使用本地函數(shù)并在其上執(zhí)行
Task.Run
。使用一個(gè)單獨(dú)的函數(shù)并
Task.Run
在其上執(zhí)行。如果您只想異步啟動(dòng)它一次并且有同步執(zhí)行函數(shù)(阻塞)的用例,那么您應(yīng)該保持這樣的函數(shù)并
Task.Run
在調(diào)用它時(shí)對(duì)其進(jìn)行操作。
另外正如我在接受的答案下的評(píng)論中提到的那樣,使用 Load 事件并在構(gòu)造函數(shù)中這樣做會(huì)更好:Load += async (o, e) => await Task.Run(() => ExecuteServer("test"));
。
不僅解決了在構(gòu)造函數(shù)中啟動(dòng)長(zhǎng)時(shí)間運(yùn)行的任務(wù)的問(wèn)題,而且還使調(diào)用在函數(shù)內(nèi)部沒(méi)有任何丑陋的嵌套而異步調(diào)用ExecuteServer
(參見(jiàn)第 3 點(diǎn))。
如果您希望ExecuteServer
函數(shù)本身是異步的,請(qǐng)參閱第 1 點(diǎn)和第 2 點(diǎn)。

TA貢獻(xiàn)1813條經(jīng)驗(yàn) 獲得超2個(gè)贊
await Task.Run(() => {...});
在ExecuteServer的開(kāi)頭使用,將它的代碼放在里面{...}
。
PS 在使用上面的代碼之前,如果您使用 UI 中的任何組件,請(qǐng)將其屬性插入變量中。像這樣:var name = txtName.Text;
并使用變量。
- 2 回答
- 0 關(guān)注
- 159 瀏覽
添加回答
舉報(bào)