[英]C# Application not exiting on Shutdown (sometimes)
我的應用程序阻止 windows 關閉,但僅在某些計算機上,而不是所有時間。 調試起來有點棘手。 我認為這是由於我的 TCP 服務器造成的。 它是一個異步服務器,我的應用程序處理 CloseReason == WindowsShutDown。 發生這種情況時,我的應用程序仍作為進程運行,但無法從任務欄/系統托盤訪問。
我想知道是否有人可以看到我的服務器代碼有任何明顯的問題。
下面是我的服務器的代碼。 從主 forms Close() 事件調用 Stop() 方法。
public class MantraServer
{
protected int portNumber;
private bool ShuttingDown = false;
//the main socket the server listens to
Socket listener;
//Constructor - Start a server on the given IP/port
public MantraServer(int port, IPAddress IP)
{
this.portNumber = port;
Start(IP);
}
///
/// Description: Start the threads to listen to the port and process
/// messages.
///
public void Start(IPAddress IP)
{
try
{
//We are using TCP sockets
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
//Assign the any IP of the machine and listen on port number 3000
IPEndPoint ipEndPoint = new IPEndPoint(IP, 3000);
//Bind and listen on the given address
listener.Bind(ipEndPoint);
listener.Listen(10);
//Accept the incoming clients
listener.BeginAccept(new AsyncCallback(OnAccept), listener);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "MANTRA Network Start Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// Decription: Stop the threads for the port listener.
public bool Stop()
{
try
{
ShuttingDown = true;
listener.Shutdown(SocketShutdown.Both);
listener.Close();
listener = null;
System.Threading.Thread.Sleep(500); //wait for half second while the server closes
return true;
}
catch (Exception)
{
return false;
}
}
///
/// Decription: Call back method to accept new connections.
/// <param name="ar">Status of an asynchronous operation.</param>
private void OnAccept(IAsyncResult ar)
{
try
{
if (!ShuttingDown)
{
MantraStatusMessage InMsg = new MantraStatusMessage();
InMsg.Socket = ((Socket)ar.AsyncState).EndAccept(ar);
//Start listening for more clients
listener.BeginAccept(new AsyncCallback(OnAccept), listener);
//Once the client connects then start receiving the commands from them
InMsg.Socket.BeginReceive(InMsg.buffer, 0, InMsg.buffer.Length, SocketFlags.None,
new AsyncCallback(OnReceive), InMsg);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "MANTRA Network Accept Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
///
/// Receives the data, puts it in a buffer and checks if we need to receive again.
public void OnReceive(IAsyncResult result)
{
MantraStatusMessage InMsg = (MantraStatusMessage)result.AsyncState;
int read = InMsg.Socket.EndReceive(result);
if (read > 0)
{
for (int i = 0; i < read; i++)
{
InMsg.TransmissionBuffer.Add(InMsg.buffer[i]);
}
//we need to read again if this is true
if (read == InMsg.buffer.Length)
{
InMsg.Socket.BeginReceive(InMsg.buffer, 0, InMsg.buffer.Length, SocketFlags.None, OnReceive, InMsg);
Console.Out.WriteLine("Message Too big!");
}
else
{
Done(InMsg);
}
}
else
{
Done(InMsg);
}
}
///
/// Deserializes and outputs the received object
public void Done(MantraStatusMessage InMsg)
{
Console.Out.WriteLine("Received: " + InMsg.msg);
MantraStatusMessage received = InMsg.DeSerialize();
Console.WriteLine(received.msg.Message);
}
}
編輯
感謝 Hogan,關於調用 Close() 的更多信息:
不允許發送或接收數據的請求,因為未連接套接字並且(當使用 sendto 調用在數據報套接字上發送時)未提供地址。
還不完全確定這意味着什么。
您必須在 windows 事件日志中添加一些日志記錄才能查看發生了什么。
最好的起點是返回 false 的捕獲(因為這將阻止 windows 關閉。)如果您在那里記錄原因,那么至少您可以查看事件日志以了解您的服務不會關閉的原因。
您應該始終確保在回調發生時為任何異步方法調用 EndXXX 對應方法。 你沒有這樣做:
InMsg.Socket = ((Socket)ar.AsyncState).EndAccept(ar);
因為它存在於!shuttingDown
塊中。 調用它...捕獲錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.