简体   繁体   English

当所有进程都在c#中的单独线程上运行时,如何保持控制台应用程序打开?

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

I am trying to make a simple server application to learn the basics of multi threaded server programming in c#. 我正在尝试制作一个简单的服务器应用程序,以学习c#中的多线程服务器编程的基础。 The basic idea is simple: the client connects to the server and sends: "get time" to receive to current time of the server. 基本思想很简单:客户端连接到服务器并发送:“获取时间”以接收服务器的当前时间。 All of the tcplistener threads and sockets should be running on seperate threads. 所有tcplistener线程和套接字都应在单独的线程上运行。 I am not sure why, but when the application finishes initializing all of the threads, the console app closes. 我不确定为什么,但是当应用程序完成所有线程的初始化时,控制台应用程序将关闭。

Here is the server code: 这是服务器代码:

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;
    }
}

In general, best practice is for a console application to offer an "Enter any key to exit" prompt when the user wants to stop the application. 通常,最佳实践是控制台应用程序在用户想要停止应用程序时提供“输入要退出的任何键”提示。 But you can always query for a specific key-press to quit, such as 'q'. 但是您始终可以查询要退出的特定按键,例如“ q”。

Here is some code to get you started: 以下是一些入门代码:

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

You need to join your threads before exiting. 你需要加入退出之前你的线程。

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

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

When your program calls Thread.Join, it is telling the operating system that it needn't schedule the main thread for any timeslices until the child thread is finished. 当您的程序调用Thread.Join时,它告诉操作系统在子线程完成之前,不需要为任何时间片安排主线程。 This makes it lighter weight than other techniques, such as busywaiting (ie running a while loop); 与其他技术(例如,忙等待(即运行while循环))相比,它的重量更轻。 while the main thread will still hold onto resources, it won't consume any CPU time. 尽管主线程仍将保留资源,但不会占用任何CPU时间。

See also When would I use Thread.Join? 另请参阅何时使用Thread.Join? and c# Waiting for multiple threads to finish c#等待多个线程完成

Your code doesn't start new thread! 您的代码不会启动新线程! So, i made some changes in your code: 因此,我对您的代码进行了一些更改:

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.

相关问题 如何读取所有当前进程并在控制台中打印它们? / C# ConsoleApp System.Diagnostics - How can I read all current processes and print them in console? / C# ConsoleApp System.Diagnostics 如何枚举 C# 中的所有托管线程? - How can I enumerate all managed threads in C#? 在 C# DLL 文件中作为进程运行时,如何获取控制台应用程序输出? - How can I obtain console application output when running it as a process in a C# DLL file? 如何使用 C# 从 windows Temp 文件夹中删除所有文件? (当进程运行时) - How do you delete all files from the windows Temp folder using C#? (When the processes are running) ac#控制台应用程序中止时如何终止子进程? - How to terminate child processes when a c# console application is aborted? 如何使用多个线程执行控制台应用程序C# - How to execute console app using multiple threads c# 在 vs 代码中运行 c# 代码时,我没有打开控制台 - When running a c# code in vs code, i doesn't open the console 如何在 C# 控制台应用程序中使用音效? - How can I use sound effect in C# console app? 如何评估 c# 控制台应用程序中的 Excel 功能? - How can I evaluate Excel functions in c# Console App? 我如何在 c# 控制台的同一列中通过线程并排打印 2 个作品? - How Can i Print 2 Works by threads side by side in same column in c# Console?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM