線程池

“線程池”是可以用來在後臺執行多個任務的線程集合。這使主線程可以自由地異步執行其他任務。

線程池通常用於服務器應用程序。每個傳入請求都將分配給線程池中的一個線程,因此可以異步處理請求,而不會佔用主線程,也不會延遲後續請求的處理。

一旦池中的某個線程完成任務,它將返回到等待線程隊列中,等待被再次使用。這種重用使應用程序可以避免爲每個任務創建新線程的開銷。

線程池通常具有最大線程數限制。如果所有線程都繁忙,則額外的任務將放入隊列中,直到有線程可用時才能夠得到處理。

您可以實現自己的線程池,但是通過 ThreadPool 類使用 .NET Framework 提供的線程池更容易一些。

下面的示例使用 .NET Framework 線程池實現單線程下載和多個線程下載的效果:

前臺界面如下:

後臺代碼:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;

namespace WindowsForm多線程複習
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ThreadStart start = new ThreadStart(DownLoad);
            Thread thread = new Thread(start);
            thread.Start();
        }

        private void Mianji(object r)
        {
            double result = Math.PI * Convert.ToInt32(r) * Convert.ToInt32(r);
            this.Invoke(new Action(delegate()
            {
                MessageBox.Show(result.ToString());
            }));
        }
        private void DownLoad()
        {
            for (int i = 30000; i < 30010; i++)
            {
                try
                {
                    using (WebClient client = new WebClient())
                    {
                        client.DownloadFile(@"http://job.cnblogs.com/offer/" + i + "/", @"G:\movices\" + i + ".html");
                        //使用匿名委託的簡寫方式
                        this.Invoke(new Action(delegate()
                        {
                            this.textBox1.AppendText("第" + i + "個帖子已經下載完成\n");

                        }));
                    }
                }
                catch (Exception ex) { }
           
            }
            Action action = new Action(Msg);
            this.Invoke(action);
       
        }
        private void Msg()
        { MessageBox.Show("下載完成"); }
       
        private void button2_Click(object sender, EventArgs e)
        {
            ParameterizedThreadStart start = new ParameterizedThreadStart(Mianji);
            Thread thread = new Thread(start);
            thread.Start(5);
        }
        //使用線程池下載帖子
        private void button3_Click(object sender, EventArgs e)
        {
            //這麼寫其實只是讓線程池啓動了一個線程,沒有利用多線程來操作
            WaitCallback wait = new WaitCallback(DownLoadThreadPool);
            ThreadPool.QueueUserWorkItem(wait);

        }
        private void DownLoadThreadPool(object obj)
        {
            for (int i = 30000; i < 30010; i++)
            {
                try
                {
                    using (WebClient client = new WebClient())
                    {
                        client.DownloadFile(@"http://job.cnblogs.com/offer/" + i + "/", @"g:\movices\" + i + ".html");
                        //使用匿名委託的簡寫方式
                        this.Invoke(new Action(delegate()
                        {
                            this.textBox1.AppendText("第" + i + "個帖子已經下載完成\n");
                        }));
                    }
                }
                catch (Exception ex) { }
            }
            Action action = new Action(Msg);
            this.Invoke(action);
       
        }
        //線程池多現場下載
        private void button4_Click(object sender, EventArgs e)
        {
            for (int i = 30000; i < 30020; i++)
            {
                WaitCallback wait = new WaitCallback(DownLoadThreadPool2);
                ThreadPool.QueueUserWorkItem(wait, i);
            }
        }
        private void DownLoadThreadPool2(object obj)
        {
            try
            {
                using (WebClient client = new WebClient())
                {
                    client.DownloadFile(@"http://job.cnblogs.com/offer/" + Convert.ToInt32(obj) + "/", @"g:\movices\" + Convert.ToInt32(obj) + ".html");
                    //使用匿名委託的簡寫方式
                    this.Invoke(new Action(delegate()
                    {
                        this.textBox1.AppendText("第" + Convert.ToInt32(obj) + "個帖子已經下載完成\n");
                    }));
                }
            }
            catch (Exception ex) { }
        }
    }
}

分別實現一下兩種效果:

從以上可以看出使用線程池,並不是先放進去的方法先執行,而是線程池根據實際情況自己來決定先執行哪個方法。還有就是並不是向線程池放進幾個委託,線程池就開啓幾個線程去執行,而是根據cpu以及內存的使用情況,自己決定開啓幾個線程,也許你放進去10個委託,而線程池只開啓了3個線程來執行

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章