)C#線程系列講座(3):線程池和檔案下載伺服器

來源:互聯網
上載者:User
如果設計一個伺服器程式,每當處理使用者請求時,都開始一個線程,將會在一定程式上消耗伺服器的資源。為此,一個最好的解決方案就是在伺服器啟動之前,事先建立一些線程對象,然後,當處理用戶端請求時,就從這些建好的線程中獲得線程對象,並處理請求。儲存這些線程對象的結構就叫做線程池。

    在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(buffer, 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();  // 開始運行監聽線程
        }
    }
}




    FileServer類的使用方法:

    FileServer fs = new FileServer(“d:\\download”);

fs.start(); // 連接埠為1234

如果d:"download目錄中有一個叫aa.exe的檔案,在瀏覽器中輸入如下的地址可下載:
    http://localhost:1234/aa.exe

為下載對話方塊:

要注意的是,本程式並沒有處理含有中文和其他特殊字元(如空格)的url,因為,檔案名稱要為英文名(不能有空格等特殊字元)。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.