C#线程系列讲座(3):线程池和文件下载服务器
生活随笔
收集整理的這篇文章主要介紹了
C#线程系列讲座(3):线程池和文件下载服务器
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
如果設計一個服務器程序,每當處理用戶請求時,都開始一個線程,將會在一定程序上消耗服務器的資源。為此,一個最好的解決方法就是在服務器啟動之前,事先創建一些線程對象,然后,當處理客戶端請求時,就從這些建好的線程中獲得線程對象,并處理請求。保存這些線程對象的結構就叫做線程池。 在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,因為,文件名要為英文名(不能有空格等特殊字符)。
本文轉自 androidguy 51CTO博客,原文鏈接:http://blog.51cto.com/androidguy/216664,如需轉載請自行聯系原作者
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,因為,文件名要為英文名(不能有空格等特殊字符)。
本文轉自 androidguy 51CTO博客,原文鏈接:http://blog.51cto.com/androidguy/216664,如需轉載請自行聯系原作者
總結
以上是生活随笔為你收集整理的C#线程系列讲座(3):线程池和文件下载服务器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《重构,改善既有代码的设计》读书笔记
- 下一篇: 管理大批量并发处理