![](/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.