簡體   English   中英

當所有進程都在c#中的單獨線程上運行時,如何保持控制台應用程序打開?

[英]How can I keep a Console App open when all processes are running on separate threads in c#?

我正在嘗試制作一個簡單的服務器應用程序,以學習c#中的多線程服務器編程的基礎。 基本思想很簡單:客戶端連接到服務器並發送:“獲取時間”以接收服務器的當前時間。 所有tcplistener線程和套接字都應在單獨的線程上運行。 我不確定為什么,但是當應用程序完成所有線程的初始化時,控制台應用程序將關閉。

這是服務器代碼:

class Program
{
    static public int minPort;
    static public int maxPort;
    static int openPort = 0;
    static byte[] sendData = new byte[1024];
    static TcpListener[] listeners;
    static Thread[] connectionThreads;

    static void Main()
    {
        Console.Write("What do you want your minimum port to be? ");
        minPort = Convert.ToInt32(Console.ReadLine());
        Console.Write("What do you want your maximum port to be? ");
        maxPort = Convert.ToInt32(Console.ReadLine());

        //init
        ThreadStart streamThreadStart = new ThreadStart(DataStream);
        openPort = maxPort - minPort;
        listeners = new TcpListener[maxPort - minPort];
        connectionThreads = new Thread[maxPort - minPort];

        for (int i = 0; i == maxPort - minPort; i++)
        {
            listeners[i] = new TcpListener(IPAddress.Any, minPort + i);
            connectionThreads[i] = new Thread(streamThreadStart);
            Thread.Sleep(10);
            openPort = openPort + 1;
        }
    }

    static void DataStream()
    {
        int port = openPort;
        byte[] receiveData = new byte[1024];
        listeners[openPort].Start();
        Socket socket = listeners[port].AcceptSocket();
        NetworkStream stream = new NetworkStream(socket);
        while (true)
        {
            socket.Receive(receiveData);
            Console.WriteLine("Received: " + BitConverter.ToString(receiveData));
            socket.Send(parseCommand(receiveData));
        }

    }
    static byte[] parseCommand(byte[] input)
    {
        string RCommand = BitConverter.ToString(input);
        string SCommand;
        if (RCommand == "get time")
        {
            SCommand = DateTime.Now.ToUniversalTime().ToString();
        }else
        {
            SCommand = "Unknown Command, please try again";
        }
        byte[] output = Encoding.ASCII.GetBytes(SCommand);
        return output;
    }
}

通常,最佳實踐是控制台應用程序在用戶想要停止應用程序時提供“輸入要退出的任何鍵”提示。 但是您始終可以查詢要退出的特定按鍵,例如“ q”。

以下是一些入門代碼:

Console.WriteLine("Press any key to exit..."); Console.ReadKey();

你需要加入退出之前你的線程。

static public void Main()
{
    /*
        Existing code goes here
    */

    //Before exiting, make sure all child threads are finished
    foreach (var thread in connectionThreads) thread.Join(); 
}

當您的程序調用Thread.Join時,它告訴操作系統在子線程完成之前,不需要為任何時間片安排主線程。 與其他技術(例如,忙等待(即運行while循環))相比,它的重量更輕。 盡管主線程仍將保留資源,但不會占用任何CPU時間。

另請參閱何時使用Thread.Join? c#等待多個線程完成

您的代碼不會啟動新線程! 因此,我對您的代碼進行了一些更改:

class Program
    {
        static public int minPort;
        static public int maxPort;
        //static int openPort = 0;
        static byte[] sendData = new byte[1024];
        static TcpListener[] listeners;
        static Thread[] connectionThreads;

        static void Main()
        {
            Console.Write("What do you want your minimum port to be? ");
            minPort = Convert.ToInt32(Console.ReadLine());
            Console.Write("What do you want your maximum port to be? ");
            maxPort = Convert.ToInt32(Console.ReadLine());

            //init
           // ThreadStart streamThreadStart = new ThreadStart(DataStream(0));
            //openPort = minPort;
            listeners = new TcpListener[maxPort - minPort];
            connectionThreads = new Thread[maxPort - minPort];

            //for (int i = 0; i == maxPort - minPort; i++) it can't work
            for (int i = 0; i < maxPort - minPort; i++)
            {
                listeners[i] = new TcpListener(IPAddress.Any, minPort + i);
                connectionThreads[i] = new Thread(new ParameterizedThreadStart(DataStream)); //thread with start parameter
                connectionThreads[i].Start(i); // start thread with index
                Thread.Sleep(10);

            }

        }

        static void DataStream(object o)
        {
            int index = (int)o; //get index
            byte[] receiveData = new byte[1024];
            listeners[index].Start(); // start listener with right index
            Socket socket = listeners[index].AcceptSocket();
            NetworkStream stream = new NetworkStream(socket);
            while (true)
            {
                socket.Receive(receiveData);
                Console.WriteLine("Received: " + BitConverter.ToString(receiveData));
                socket.Send(parseCommand(receiveData));
            }

        }
        static byte[] parseCommand(byte[] input)
        {
            string RCommand = BitConverter.ToString(input);
            string SCommand;
            if (RCommand == "get time")
            {
                SCommand = DateTime.Now.ToUniversalTime().ToString();
            }
            else
            {
                SCommand = "Unknown Command, please try again";
            }
            byte[] output = Encoding.ASCII.GetBytes(SCommand);
            return output;
        }
    }

暫無
暫無

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

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