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.Net.Sockets;
using System.Threading;
using System.IO;//......        public static int ThreadCount = 5;//线程数量
        public static Thread[] Downloaders;//下载线程
        public static string FileURL = "";//文件URL
        public static string SavePath = "";//保存路径
        public long FileSize;//文件大小
        public int DownloadSize;//已经完成的下载字节数
        public int ThreadComplete;//完成线程数
        public bool isWriting = false;//是否在占用文件
        public bool[] ThreadWritingComplete = new bool[ThreadCount];        public delegate void MyInvoke(string str1,string str2);
        public void FormMessage(string arg,string command)
        {
            switch (arg)
            {
                case "text":
                    richTextBox1.AppendText("\n" + command);
                    break;
                default:
                    break;
            }
        }
private void button1_Click(object sender, EventArgs e)
        {
            MyInvoke mi = new MyInvoke(FormMessage);
            FileURL = textBox1.Text;//Http下载地址
            SavePath = textbox2.Text;            HttpWebRequest request= (HttpWebRequest)WebRequest.Create(FileURL);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            FileSize = response.ContentLength;
            int SingleWork = (int)(FileSize / ThreadCount);//每个分配
            int Rest = (int)(FileSize % ThreadCount);//剩下的
            request.Abort();
            response.Close();//释放            //MessageBox.Show(FileSize.ToString());            for (int i = 0; i < ThreadCount; i++)
            {
                List<int> range = new List<int>();
                range.Add(i * SingleWork);
                if (Rest > 0 && (ThreadCount - 1) == i)
                {
                    range.Add(i * SingleWork + SingleWork + Rest - 1);
                }
                else
                {
                    range.Add(i * SingleWork + SingleWork);
                }
                Downloaders = new Thread[ThreadCount];
                Downloaders[i] = new Thread(() => { Download(range[0], range[1],i); });
                Downloaders[i].Name = "Thread " + (i + 1).ToString();
                this.BeginInvoke(mi, new object[] { "text", "Thread" + (i + 1).ToString() + "开始" });
                Downloaders[i].Start();
            }        public void Download(int From, int To,int ThreadNum)
        {
            MyInvoke mi = new MyInvoke(FormMessage);
            //MessageBox.Show(From.ToString() + "  " + To.ToString(),ThreadNum.ToString());
            Stream httpFileStream = null;
            Stream localFileStream = null;
            try
            {
                HttpWebRequest Download_HttpWebRequest = (HttpWebRequest)WebRequest.Create(FileURL);
                Download_HttpWebRequest.AddRange(From, To);
                HttpWebResponse Download_HttpWebResponse = (HttpWebResponse)Download_HttpWebRequest.GetResponse();
                httpFileStream = Download_HttpWebResponse.GetResponseStream();
                localFileStream = new FileStream(SavePath+".NDTTemp"+ThreadNum.ToString(), FileMode.Create);
                BinaryReader httpBinary = new BinaryReader(httpFileStream);
                BinaryWriter localBinary = new BinaryWriter(localFileStream);
                byte[] RecieveByte = new byte[5000];
                //int GetByteSize = httpFileStream.Read(RecieveByte, 0, RecieveByte.Length);
                int GetByteSize = httpBinary.Read(RecieveByte, 0, RecieveByte.Length);
                while (GetByteSize > 0)
                {
                    //Thread.Sleep(20);
                    DownloadSize += GetByteSize;
                    
                        //localFileStream.Write(RecieveByte, 0, RecieveByte.Length);
                    localBinary.Write(RecieveByte, 0, RecieveByte.Length);
                        GetByteSize = httpFileStream.Read(RecieveByte, 0, RecieveByte.Length);
                    
                }
                ThreadComplete++; 
                this.BeginInvoke(mi, new object[] { "text", "Thread" + (ThreadComplete).ToString() + "完成" });
            }
            catch(Exception err)
            {
                MessageBox.Show(err.Message);
            }
            finally
            {
                if (httpFileStream != null)
                {
                    httpFileStream.Dispose();
                }
                if (localFileStream != null)
                {
                    localFileStream.Dispose();
                }
            }
            if (ThreadComplete == ThreadCount)//全部完成
            {
                Complete();
            }
            
        }
public void Complete()
        {
            MyInvoke mi = new MyInvoke(FormMessage);
            this.BeginInvoke(mi, new object[] { "text", "开始合并文件" });
            FileStream fs = new FileStream(SavePath, FileMode.Create);
            BinaryWriter bw = new BinaryWriter(fs);
            for(int i=0;i<ThreadCount;i++)
            {
                
                FileStream TempFS = new FileStream(SavePath + ".NDTTemp" + (i + 1).ToString(), FileMode.Open);
                this.BeginInvoke(mi, new object[] { "text", "开始合并文件"+TempFS.Name+"" });
                BinaryReader br = new BinaryReader(TempFS);
                bw.Write(br.ReadBytes((int)TempFS.Length));
                br.Close();
                TempFS.Close();
                //File.Delete("......");
            }
            bw.Close();
        }
      
下载下来的文件有几个Part是0字节,合并后少几个M求高人。

解决方案 »

  1.   

    BeginInvoke是异步的,不会阻止后面代码执行,而 BeginInvoke前面进行了ThreadComplete++; 这就可能引起条件if (ThreadComplete == ThreadCount)//全部完成得到满足,但是并没有下载完成,从而触发了 Complete
      

  2.   

    我把所有BeginInvoke去掉后下载,文件大小没怎么变,但是是损坏的。里面有一大片长度约有1024的“00”字节。