您的位置:首页 > 编程语言 > C#

C#线程系列讲座(3):线程池和文件下载服务器

2015-11-27 09:48 399 查看
如果设计一个服务器程序,每当处理用户请求时,都开始一个线程,将会在一定程序上消耗服务器的资源。为此,一个最好的解决方法就是在服务器启动之前,事先创建一些线程对象,然后,当处理客户端请求时,就从这些建好的线程中获得线程对象,并处理请求。保存这些线程对象的结构就叫做线程池。

    在C#中可以通过System.Threading.ThreadPool类来实现,在默认情况下,ThreadPool最大可建立500个工作线程和1000个I/O线程(根据机器CPU个数和.net framework版本的不同,这些数据可能会有变化)。下面是一个用C#从线程池获得线程的例子:

private static void execute(object state)

{

    Console.WriteLine(state);      

}
static void Main(string[] args)

{

  

    int workerThreads;

    int completionPortThreads;

         

    ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);

    Console.WriteLine(workerThreads);

    Console.WriteLine(completionPortThreads);    

    ThreadPool.QueueUserWorkItem(execute,"线程1");   // 从线程池中得到一个线程,并运行execute
    ThreadPool.QueueUserWorkItem(execute, "线程2");

    ThreadPool.QueueUserWorkItem(execute, "线程3");

    Console.ReadLine();

}

    下图为上面代码的运行结果。



    要注意的是,使用ThreadPool获得的线程都是后台线程。

    下面的程序是我设计的一个下载文件服务器的例子。这个例子从ThreadPool获得线程,并处理相应的客户端请求。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.IO;

namespace MyThread

{

    class FileServer

    {

        private String root;

        private Thread listenerThread;

        private void worker(object state)

        {

             TcpClient client = state as TcpClient;

             try

             {

                 client.ReceiveTimeout = 2000;

                 Stream stream = client.GetStream();

                 System.IO.StreamReader sr = new StreamReader(stream);

                 String line = sr.ReadLine();

                 String[] array = line.Split(' ');

                 String path = array[1].Replace('/', '\\');

                 String filename = root + path;

                 if (File.Exists(filename))  // 如果下载文件存在,开始下载这个文件
                 {

                     FileStream fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read,

                                                           FileShare.Read);

                     byte[] buffer = new byte[8192]; // 每次下载8K
                     int count = 0;

                     String responseHeader = "HTTP/1.1 200 OK\r\n" +

                                             "Content-Type:application/octet-stream\r\n" +

                                             "Content-Disposition:attachment;filename=" +

                                                   filename.Substring(filename.LastIndexOf("\\") + 1) + "\r\n\r\n";

                     byte[] header = ASCIIEncoding.ASCII.GetBytes(responseHeader);

                     stream.Write(header, 0, header.Length);

                     while ((count = fileStream.Read(buffer, 0, buffer.Count())) > 0)

                     {

                         stream.Write(bu
d445
ffer, 0, count);

                     }

                     Console.WriteLine(filename + "下载完成");

                 }

                 else  // 文件不存在,输出提示信息
                 {

                     String response = "HTTP/1.1 200 OK\r\nContent-Type:text/plain;charset=utf-8\r\n\r\n文件不存在";

                     byte[] buffer = ASCIIEncoding.UTF8.GetBytes(response);

                     stream.Write(buffer, 0, buffer.Length);

                 }

             }

             catch (Exception e)

             {

                 Console.WriteLine(e.Message);

             }

             finally

             {

                 if (client != null)

                 {

                     client.Close();

                 }

             }

        }

        private void listener()

        {

            TcpListener listener = new TcpListener(1234);

            listener.Start();  // 开始监听客户端请求
            TcpClient client = null;

            while (true)

            {

                client = listener.AcceptTcpClient();

                client.ReceiveTimeout =2000;

                ThreadPool.QueueUserWorkItem(worker, client);  // 从线程池中获得一个线程来处理客户端请求
            }

        }

        public FileServer(String root)

        {

            this.root= root;        

        }

        public void start()

        {

            listenerThread = new Thread(listener);

            listenerThread.Start();  // 开始运行监听线程
        }

    }

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: