![](/img/trans.png)
[英]What's the best way to shut down a .Net winforms application and delete the executable
[英]Proper way to shut down socket server in WinForms application?
我正在使用C#中的基本套接字服務器進行工作,該服務器需要作為Windows Forms應用程序的一部分運行。 我從MSDN的異步套接字服務器代碼開始。 像許多套接字服務器代碼示例一樣,這是一個控制台模式應用程序。 這是從Main()調用的StartListening()方法的示例:
public static void StartListening()
{
// data buffer for incoming data
byte[] bytes = new byte[1024];
IPAddress ipAddress = IPAddress.Parse(serverIpAddress);
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, portNumber);
// create TCP/IP socket
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// bind socket to the local endpoint and listen for incoming connections
try
{
serverSocket.Bind(localEndPoint);
serverSocket.Listen(100);
while (true)
{
// set the allDone ManualResetEvent to nonsignaled state
allDone.Reset();
// start an asynchronous socket to listen for connections
Console.WriteLine("Waiting for a connection...");
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), serverSocket);
// wait until a connection is made before continuing
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
如您所見,其中有一個while(true)循環,該循環使用ManualResetEvent等待進入客戶端連接,然后進入While循環的下一個迭代。 我不確定為什么它們包含Console.WriteLine(\\n"Press ENTER to continue...")
語句,因為沒有辦法打破while(true)循環。
無論如何,在考慮將其轉換為WinForms應用程序時,我顯然需要在另一個線程上運行服務器,但是當用戶關閉我的應用程序時,我要確保套接字服務器“正確”關閉。 我的最佳猜測是關閉任何打開的客戶端連接,中斷偵聽循環,然后關閉服務器套接字(不一定按此順序)。
我已經看到一些建議,這些建議只建議使服務器線程成為后台線程,並在應用程序關閉時讓它被銷毀,但這似乎不太“干凈”。 例如,如果關閉了客戶端的連接並在應用程序關閉時發送數據,那么這對客戶端有什么作用? 任何人都可以建議有關正確關閉套接字服務器的“最佳實踐”嗎?
我會將整個內容包裝在Task中,並使用取消標記。
有關使用任務和取消令牌的良好示例,請參閱https://msdn.microsoft.com/zh-cn/library/hh160373(v=vs.110).aspx 。 當您要關閉套接字服務器時,可以使取消令牌取消任務。
在任務內部會引發異常。 在異常處理程序中,您調用Socket.Close,這將停止BeginAccept調用(將調用EndAccept,但Socket.Handle將為-1)。
實際上,您不需要線程,因為您已經在異步監聽。
只需在AcceptCallback
的結尾再次調用serverSocket.BeginAccept
。 然后,服務器的關閉將減少為serverSocket.Close()
(顯然, serverSocket
必須是一個類字段)。
最后,在AcceptCallback
您需要捕獲EndAccept
的異常。 順便說一句,這就是為什么在示例中出現Console.Writeline
和Console.Readkey
的原因:當發生異常時執行。
此塊:Console.WriteLine(“ \\ n按ENTER繼續...”); Console.Read(); 那里是因為編寫此方法的方式,如果引發異常,它將退出循環。
我會這樣寫以適合您的參數:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { private Socket serverSocket; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { StartListening(); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { serverSocket.Close(); } public void StartListening() { byte[] bytes = new byte[1024]; IPAddress ipAddress = IPAddress.Parse(serverIpAddress); IPEndPoint localEndPoint = new IPEndPoint(ipAddress, portNumber); serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { serverSocket.Bind(localEndPoint); serverSocket.Listen(100); while(true) { allDone.Reset(); Console.WriteLine("Waiting for a connection..."); serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), serverSocket); // wait until a connection is made before continuing allDone.WaitOne(); } } catch(Exception e) { Console.WriteLine(e.ToString()); } finally { serverSocket.Close(); } Console.WriteLine("\\nPress ENTER to continue..."); Console.Read(); } } }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.