簡體   English   中英

關閉TCP連接並退出應用程序的方法

[英]Way to close TCP Connection and Exit Application

這是一個TCP程序,該程序從TCP連接接收數據,然后解析該數據並將其傳輸到另一個TCP連接。 當我退出應用程序時,它不起作用。 它將作為進程保留在系統中。

由於我不是一個非常有經驗的開發人員,請有人可以幫助我找到此代碼中的錯誤。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace Machine_Feeder
{
    public partial class FeederControlMonitor : Form
    {
        TcpListener Listener = null;
        public string Status = string.Empty;
        public Thread T = null;
        public FeederControlMonitor()
        {
            InitializeComponent();
         }

        private void FeederControlMonitor_Load(object sender, EventArgs e)
        {
            txtStatus.Text = "Feeder waiting for data...";
            ThreadStart Ts = new ThreadStart(StartReceiving);
            T = new Thread(Ts);
            T.Start();
        }
        public void StartReceiving()
        {
            ReceiveTCP(9100);
        }
        public void ReceiveTCP(int portN)
        {

            try
            {
                Listener = new TcpListener(IPAddress.Any, portN);
                Listener.Start();

            }
            catch (Exception ex)
            {
                File.WriteAllText(@"C:\\Drive\\ex.txt", ex.Message);
                Console.WriteLine(ex.Message);
            }
       try
            {
                while (true)
                {
                    Socket client = Listener.AcceptSocket();
                    var childSocketThread = new Thread(() =>
                    {
                        byte[] data = new byte[10000];
                        int size = client.Receive(data);
                        ParseData(System.Text.Encoding.Default.GetString(data));
                        client.Close();
                    });
                    childSocketThread.Start();
                    }
                    Listener.Stop();
  }
            catch (Exception ex)
            {
                File.WriteAllText(@"C:\\Drive\\ex.txt", ex.Message);
            }
        }

        public void ParseData(string data)
        {
            var useFulData = data.Substring(data.IndexOf("F1")).Replace("  ", " ");// Space
            useFulData = useFulData.Remove(useFulData.IndexOf("<ETX>"));
            string[] delimeters = { "<DEL>", "<ESC>" };
            var listOfValues = useFulData.Split(delimeters, StringSplitOptions.None).ToList();
            int pos = 0;
            for (int i = 1; i < listOfValues.Count; i += 2, pos++)
            {
                listOfValues[pos] = listOfValues[i];
            }
            listOfValues.RemoveRange(pos, listOfValues.Count - pos);
            txtHealthCard.Invoke((Action)delegate { txtHealthCard.Text = listOfValues[0]; });
            txtCID.Invoke((Action)delegate { txtCID.Text = listOfValues[1]; });
            txtMedicalFitLocation.Invoke((Action)delegate { txtMedicalFitLocation.Text = listOfValues[2]; });
            txtGender.Invoke((Action)delegate { txtGender.Text = listOfValues[3]; });
            txtAge.Invoke((Action)delegate { txtAge.Text = listOfValues[4]; });
            txtPatientName.Invoke((Action)delegate { txtPatientName.Text = listOfValues[5]; });


            MyProtocolMaker(listOfValues[5], 
                listOfValues[4], 
                listOfValues[2], 
                listOfValues[3], 
                listOfValues[8], 
                listOfValues[1], 
                listOfValues[10], 
              );
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            Listener.Stop();
            T.Abort();
            this.Close();
        }
        private void MyProtocolMaker(
            string patientName,
            string patientAge,
            string mfitLocation,
            string gender,
            string healthCardNo,
           )
        {
            string feederInfo = "^^^P^PI" + healthCardNo + "^PN" + patientName + "^PA" + patientAge + "^PS" + gender + "^P7" + mfitLocation +"^_SS^^^_S";
            System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient("127.0.0.1", 8001);
            NetworkStream serverStream = clientSocket.GetStream();
            byte[] outStream = System.Text.Encoding.ASCII.GetBytes(feederInfo);
            serverStream.Write(outStream, 0, outStream.Length);
            serverStream.Flush();
            serverStream.Close();
            clientSocket.Close();
         }

        private void FeederControlMonitor_FormClosing(object sender, FormClosingEventArgs e)
        {
            Listener.Stop();
            T.Abort();
            this.Close();
        }
    }
}

您的問題是,您正在線程中創建線程。 這些線程使應用程序保持活動狀態。 嘗試將它們標記為后台線程:( 這是紅色磁帶解決方案)

var childSocketThread = new Thread(() =>
{
    byte[] data = new byte[10000];
    int size = client.Receive(data);  // <-- the thread hangs on these and will block termination
    ParseData(System.Text.Encoding.Default.GetString(data));
    client.Close();
});
childSocketThread.IsBackground = true;   // <---
childSocketThread.Start();

當線程標記為后台(默認)時 ,它們將阻止應用程序終止。 您應該創建一個列表來存儲客戶端線程,以便可以很好地退出這些線程。


除非沒有其他方法,否則切勿中止線程。 而不是中止,您應該退出線程中的while循環。

最好的方法是使用ManualResetEvent

領域:

private ManualResetEvent _terminating = new ManualResetEvent(false);

在線程中:

while (_terminating.WaitOne(0))
{
    // thread code
}

在出口:

_terminating.Set();
T.Join();

旁注:TCP正在流式傳輸,因此僅讀取10k字節的字節就不能保證完整的數據包。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM