想问一下迅雷的多线程是怎么工作的,比如上图 有多个任务,设置了线程数为3,怎么进行线程的开始,暂停,结束,最好有类似的源码借我看一下winform多线程

解决方案 »

  1.   

    http://www.codeproject.com/Articles/21053/MyDownloader-A-Multi-thread-C-Segmented-Download-M
      

  2.   

    迅雷是基于P2p协议的 ,多线程看看这个协议  http://blog.csdn.net/kllxyu/article/details/11893005
      

  3.   


    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.Net;
    using System.Web;
    using System.IO;
    using System.Threading;namespace 多线程下载
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            #region 定义要用的变量        int my_test = 1;
            //定义 要用的变量
            //HttpWebResponse _res = null;    //通过WebRequest创建一个请求后,你可以通过请求来获取HttpWebResponse。通过HttpWebResponse.StatusCode来判断当前错误,也可以得到一些精确的消息。
            string _strResult = "";
            public static string _defaultUserAgent =  "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";   //定义默认浏览器类型
            //定义浏览器组
            //搜狗浏览器4.0 高速模式 on Windows XP x86:
            //搜狗浏览器4.0 兼容模式 on Windows XP x86 IE6:
            //360急速浏览器6.0 急速模式 on Windows XP x86:
            //360急速浏览器6.0 兼容模式 on Windows XP x86 IE6:
            //360安全浏览器5.0自带IE8内核版 on Windows XP x86 IE6:
            //猎豹浏览器2.0.10.3198 兼容模式on Windows XP x86 IE6:
            //QQ浏览器7.0 on Windows XP x86 IE6:
            //IE 7.0
            //IE 8.0
            //IE 9.0
            public static string[] _allUserAgent =new string[10]{
                "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 SE 2.X MetaSr 1.0",
            "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; SE 2.X MetaSr 1.0) ",
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
            "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
            "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; 360SE)",
            "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)",
            "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
            "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
            "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0;Trident/4.0)",
            "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1;Trident/5.0)"
        };
            public static int _timeout = 35000;    //定义请求超时时间
            Encoding _encoding = Encoding.GetEncoding("gb2312");    //编码方式
            public static string _filename;   //定义保存的文件名字
            FileInfo _file; //定义一个文件
            int _threadtotal = 3;   //定义线程总数
            long _filelenght;   //定义文件长度
            Uri _webpath;        static int _threadall = 10;    //定义线程选择框最大值
            public static string[] _threadstart = new string[_threadall];    //下载的开始位置
            public static string[] _threadnow = new string[_threadall];  //已经下载的
            public static string[] _threadalldown = new string[_threadall];  //需要下载的
            int _threading; //进行下载的线程
            delegate void _funDelegate(string[] s);   //定义调用方法的委托
            #endregion        private void button2_Click(object sender, EventArgs e)
            { 
                _threading = 0;
                _encoding = Encoding.GetEncoding(comboBox2.SelectedItem.ToString());
                _threadtotal = Convert.ToInt16(comboBox1.SelectedItem);
                _strResult = "总线程数:"+_threadtotal.ToString();
                label8.Text = _strResult;
                try
                {
                    string __strpath = textBox1.Text.ToString().Trim().Replace("\n", "").Replace("\r", "").Replace(Environment.NewLine, "");
                    textBox3.Text = __strpath;
                    __strpath = textBox3.Text.ToString();
                    _webpath = new Uri(__strpath);
                    if (_webpath == null) return;
                    sendpath(_webpath, _encoding);
                }
                catch (Exception)
                {
                    MessageBox.Show("请检查输入的路径是否正确!"); return;
                }
            }        /// <summary>  
            /// 创建GET方式的HTTP请求  
            /// </summary>  
            /// <param name="url">请求的URL</param>  
            /// <param name="timeout">请求的超时时间</param>  
            /// <param name="userAgent">请求的客户端浏览器信息,可以为空</param>  
            /// <param name="cookies">随同HTTP请求发送的Cookie信息,如果不需要身份验证可以为空</param>  
            /// <returns></returns> 
            private void sendpath(Uri path,Encoding coding)
            {
                //初始化 变量
                            //Uri path = new Uri(paths);
                //MessageBox.Show(path.ToString());
                //path = HttpUtility.UrlEncode(path, _encoding);  //对url进行编码转换
                //MessageBox.Show(path);
                HttpWebRequest _req = (HttpWebRequest)WebRequest.Create(path);  //创建http请求
                _req.Method = "GET";
                _req.UserAgent = _defaultUserAgent;
                _req.Timeout = _timeout;
                HttpWebResponse _res = _req.GetResponse() as HttpWebResponse;   //接收的内容
                //_encoding = Encoding.GetEncoding(_res.CharacterSet.ToString());
                
                //创建文件
                _filename = (textBox3.Text.ToString().Split('/')[textBox3.Text.ToString().Split('/').Length - 1]).ToString();
                _file = new FileInfo(_filename);
                FileStream __fs = _file.Create();
                _filelenght = _res.ContentLength;
                __fs.SetLength(_res.ContentLength);
                _res.Close();
                __fs.Close();            //显示检测的信息
                label2.Text = "总大小:"+_BytetoM(_filelenght);   //要下载的文件总大小
            }        private void button1_Click(object sender, EventArgs e)
            {
                button2.PerformClick();
                //开启多个线程
                //每个线程下载的文件的大小
                long blockSize = _filelenght / _threadtotal;
                _threading = _threadtotal;  //用户选择的总线程
                try
                {
                    for (int i = 1; i <= _threadtotal; i++)
                    {
                        long __startindex = (i - 1) * blockSize;
                        long __endindex = i * blockSize - 1;
                        if (i == _threadtotal)  //最后一个线程
                        {
                            __endindex = _filelenght;
                        }
                        _threadnow[i - 1] = __startindex.ToString();
                        _threadstart[i - 1] = __startindex.ToString();
                        _threadalldown[i - 1] = __endindex.ToString();
                        //MessageBox.Show(myall._threadnow[i - 1]);
                        //MessageBox.Show(i.ToString());
                        int ii = i; //让 新线程使用ii,而不是i变量
                        new Thread(new ThreadStart(() =>
                        {
                            //MessageBox.Show(ii.ToString());
                            //MessageBox.Show(myall._threadall.ToString());
                            //MessageBox.Show(myall._threadnow[0]);
                            new myDownloadThread()._downloadThread(_filename, _webpath, ii, __startindex, __endindex, ref _threadnow[ii - 1]);
                            _threading = _threading - 1;
                        })).Start();
                        //_strResult = _strResult + Environment.NewLine + "线程:" + i.ToString() + "下载-----" + __startindex.ToString() + "--->" + __endindex.ToString();
                    }
                    //__fs.Close();
                    label8.Text = _strResult;
                }
                catch (Exception)
                {
                    MessageBox.Show("开启线程出错!");
                }
                //建立监听线程
                try
                {
                    new Thread(new ThreadStart(() =>
                    {
                        while (_threading != 0)
                        {
                            Thread.Sleep(1000);
                            _updateUi(ref _threadstart, _threadnow, _threadalldown);
                        }
                    })).Start();
                }
                catch (Exception)
                {
                    MessageBox.Show("监听出错");
                }
            }
      

  4.   

            private void _updateUi(ref string[] threadstart,string[] threaddownnow,string[] threaddownall)
            {
                string __speedall;
                long __alldownsize=0;
                long __complete=0;
                string __showone="";
                string[] __speedone = new string[_threadtotal];
                string[] __st = new string[_threadtotal];
                string[] __now = new string[_threadtotal];
                //取值
                for (int i = 0; i <= _threadtotal - 1; i++)
                {
                    __st[i] = threadstart[i];
                    __now[i] = threaddownnow[i];
                }
                for (int i = 0; i <= _threadtotal-1; i++)
                {
                    __speedone[i] = (Convert.ToInt64(__now[i]) - Convert.ToInt64(__st[i])).ToString();
                    __alldownsize += Convert.ToInt64(__speedone[i]);
                    if (i == 0)
                    {
                        __complete = Convert.ToInt64(__now[i]);
                    }
                    else
                    {
                        __complete +=(Convert.ToInt64(__now[i])-Convert.ToInt64(threaddownall[i-1])+1);
                    }
                    __showone += Environment.NewLine + "进程" + (i+1).ToString() + " : " + _BytetoM(Convert.ToInt64(__speedone[i]))+"/s";
                    threadstart[i] = __now[i];
                }
                //赋值
                
                __speedall = _BytetoM(__alldownsize) + "/s";
                //更新ui
                string _label3 = "已下载:"+_BytetoM(__complete);   //已下载
                string _label4 = "下载进度:" + string.Format("{0:#0.##}", (((double)__complete / _filelenght) * 100)) + " %";   //下载进度
                string _label5 = "下载速度:" + __speedall;   //下载速度
                string _label6;
                if (__alldownsize >= 1)
                {
                    _label6 = "预计剩余时间:" + _inttotime(Convert.ToInt64(Math.Floor((double)(_filelenght - __complete) / __alldownsize)));   //剩余时间
                }
                else
                {
                    _label6 = "预计剩余时间:未知";
                }
                string _label8 = _strResult + __showone;   //总线程数
                string[] __all = new string[5] { _label3, _label4, _label5, _label6, _label8 };
                //使用委托更新
                _funDelegate __funD = new _funDelegate(_trueUpdateUi);  //要调用的方法的委托
                this.BeginInvoke(__funD, (object)__all);    //用 begininvoke和invoke都可以,被调用的方法的委托,要传递的参数[Object]数组          
            }        private void _trueUpdateUi(string[] all)
            {
                label3.Text = all[0];
                label4.Text = all[1];
                label5.Text = all[2];
                label6.Text = all[3];
                label8.Text = all[4];
            }        private string _inttotime(long itime)
            {
                long __it=itime;
                int __h;
                int __m;
                int __s;
                if(__it > (60*60*24))
                {
                    return "超过一天!";
                }
                double __f=__it / (60 * 60);
                __h = Convert.ToInt16(Math.Floor(__f));
                __it = __it%(60*60);
                __m = Convert.ToInt16(Math.Floor(__f));
                __it = __it % 60;
                __s = Convert.ToInt16(Math.Floor(__f));
                return __h.ToString() + "时" + __m.ToString() + "分" + __s.ToString() + "秒";
            }        private void Form1_Load(object sender, EventArgs e)
            {            for (int i = 1; i <= _threadall; i++)
                {                comboBox1.Items.AddRange(new object[] {i.ToString() });
                }
                comboBox1.SelectedItem = "1";
                comboBox2.Items.AddRange(new object[]{"gb2312","utf-8"});
                comboBox2.SelectedItem = "gb2312";
            }
            private string _BytetoM(long b)
            {
                float __result=b;
                string __size=" B";
                if (__result > 900)
                {
                    __result = __result / 1024;
                    __size = " KB";
                }
                if (__result > 900)
                {
                    __result = __result / 1024;
                    __size = " MB";
                }
                if (__result > 900)
                {
                    __result = __result / 1024;
                    __size = " GB";
                }            return (string.Format("{0:#0.###}", __result) + __size);
            }        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                System.Environment.Exit(0);
            }    }    //class 下载类
       public class myDownloadThread
       {
           //每个线程的下载
           public void _downloadThread(string file, Uri path, int threadid, long startindex, long endindex,ref string alldown)
           {
               //try
               //{
                   HttpWebRequest _req;
                   HttpWebResponse _res;
                   while (true)
                   {
                       _req = (HttpWebRequest)WebRequest.Create(path);  //创建http请求
                       _req.Method = "GET";
                       //_req.UserAgent = Form1._defaultUserAgent;
                       _req.UserAgent = Form1._allUserAgent[threadid-1];
                       _req.Timeout = Form1._timeout;
                       _req.AddRange(startindex, endindex);
                       try
                       {
                           _res = _req.GetResponse() as HttpWebResponse;   //接收的内容
                           if (_res.StatusCode != HttpStatusCode.PartialContent)
                           {
                               MessageBox.Show(_res.StatusCode.ToString());
                               continue;
                           }
                           break;
                       }
                       catch (Exception)
                       {
                           continue;
                       }
                   }
                   
                   Stream _so = _res.GetResponseStream();
                   FileStream __fsw = new FileStream(file, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, (int)(endindex - startindex), true);               __fsw.Seek(startindex, SeekOrigin.Begin);
                   byte[] __buffer = new byte[1024];
                   int len = 0;
                   while ((len = _so.Read(__buffer, 0, __buffer.Length)) != 0)
                   {
                       __fsw.Write(__buffer, 0, len);
                       //alldown[threadid-1] = (Convert.ToInt64(alldown[threadid-1]) + len).ToString();
                       Form1._threadnow[threadid - 1] = (Convert.ToInt64(alldown) + len).ToString();
                       //MessageBox.Show(Form1._threadnow[0]);
                       //Thread.Sleep(500);
                   }
                   _res.Close();
                   _so.Close();
                   __fsw.Close();
               //}
               //catch (Exception)
               //{
               //    MessageBox.Show("文件太大");
               //}       }
       }}