欧美大屁股bbbbxxxx,狼人大香伊蕉国产www亚洲,男ji大巴进入女人的视频小说,男人把ji大巴放进女人免费视频,免费情侣作爱视频

歡迎來到入門教程網(wǎng)!

C#教程

當(dāng)前位置:主頁 > 軟件編程 > C#教程 >

C# FileStream實(shí)現(xiàn)多線程斷點(diǎn)續(xù)傳

來源:本站原創(chuàng)|時間:2020-01-10|欄目:C#教程|點(diǎn)擊: 次

一、前言

       網(wǎng)上有許多的多線程斷點(diǎn)續(xù)傳操作,但總是寫的很云里霧里,或者寫的比較坑長。由于這幾個月要負(fù)責(zé)公司的在線升級項(xiàng)目,所以正好順便寫了一下

代碼如下:

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace TestCenter
{
 class Program
 {
  static void Main(string[] args)
  {
   string LocalSavePath = @"E:\Test\TestFile\Local\1.msi"; //本地目標(biāo)文件路徑

   FileInfo SeverFilePath = new FileInfo(@"E:\Test\TestFile\Server\1.msi"); //服務(wù)器待文件路徑
   long FileLength = SeverFilePath.Length; //待下載文件大小


   Console.WriteLine("Start Configuration");
   int PackCount = 0; //初始化數(shù)據(jù)包個數(shù)

   long PackSize = 1024000; //數(shù)據(jù)包大小

   if (FileLength % PackSize > 0)
   {
    PackCount = (int)(FileLength / PackSize) + 1;
   }

   else
   {
    PackCount = (int)(FileLength / PackSize);
   }


   Console.WriteLine("Start Recieve");
   var tasks = new Task[PackCount]; //多線程任務(wù)

   for (int index = 0; index < PackCount; index++)
   {


    int Threadindex = index; //這步很關(guān)鍵,在Task()里的絕對不能直接使用index
    var task = new Task(() =>
    {
     string tempfilepath = @"E:\Test\TestFile\Temp\" + "QS_" + Threadindex + "_" + PackCount; //臨時文件路徑

     using (FileStream tempstream = new FileStream(tempfilepath, FileMode.Create, FileAccess.Write, FileShare.Write))
     {
      int length = (int)Math.Min(PackSize, FileLength - Threadindex * PackSize);

      var bytes = GetFile(Threadindex*PackCount, length);

      tempstream.Write(bytes, 0, length);
      tempstream.Flush();
      tempstream.Close();
      tempstream.Dispose();
     }
    });
    tasks[Threadindex] = task;
    task.Start();
   }

   Task.WaitAll(tasks); //等待所有線程完成
   Console.WriteLine("Recieve End");


   //檢測有哪些數(shù)據(jù)包未下載
   Console.WriteLine("Start Compare");
   DirectoryInfo TempDir = new DirectoryInfo(@"E:\Test\TestFile\temp"); //臨時文件夾路徑
   List<string> Comparefiles = new List<string>();

   for (int i = 0; i < PackCount; i++)
   {
    bool hasfile = false;
    foreach (FileInfo Tempfile in TempDir.GetFiles())
    {
     if (Tempfile.Name.Split('_')[1] == i.ToString())
     {
      hasfile = true;
      break;
     }
    }
    if (hasfile == false)
    {
     Comparefiles.Add(i.ToString());
    }
   }

   //最后補(bǔ)上這些缺失的文件
   if (Comparefiles.Count > 0)
   {
    foreach (string com_index in Comparefiles)
    {
     string tempfilepath = @"E:\Test\TestFile\Temp\" + "QS_" + com_index+ "_" + PackCount;
     using (FileStream Compstream = new FileStream(tempfilepath, FileMode.Create, FileAccess.Write, FileShare.Write))
     {
      int length = (int)Math.Min(PackSize, FileLength - Convert.ToInt32(com_index) * PackSize);
      var bytes = GetFile(Convert.ToInt32(com_index)*PackCount, length);
      Compstream.Write(bytes, 0, length);
      Compstream.Flush();
      Compstream.Close();
      Compstream.Dispose();
     }
    }

   }
   Console.WriteLine("Compare End");


   //準(zhǔn)備將臨時文件融合并寫到1.msi中
   Console.WriteLine("Start Write");
   using (FileStream writestream = new FileStream(LocalSavePath, FileMode.Create, FileAccess.Write, FileShare.Write))
   {
    foreach (FileInfo Tempfile in TempDir.GetFiles())
    {
     using (FileStream readTempStream = new FileStream(Tempfile.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
     {
      long onefileLength = Tempfile.Length;
      byte[] buffer = new byte[Convert.ToInt32(onefileLength)];
      readTempStream.Read(buffer, 0, Convert.ToInt32(onefileLength));
      writestream.Write(buffer, 0, Convert.ToInt32(onefileLength));
     }
    }
    writestream.Flush();
    writestream.Close();
    writestream.Dispose();
   }
   Console.WriteLine("Write End");



   //刪除臨時文件
   Console.WriteLine("Start Delete Temp Files");
   foreach (FileInfo Tempfile in TempDir.GetFiles())
   {
    Tempfile.Delete();
   }
   Console.WriteLine("Delete Success");
   Console.ReadKey();
  }


  //這個方法可以放到Remoting或者WCF服務(wù)中去,然后本地調(diào)用該方法即可實(shí)現(xiàn)多線程斷點(diǎn)續(xù)傳
  public static byte[] GetFile(int start, int length)
  {
   string SeverFilePath = @"E:\Test\TestFile\Server\1.msi";
   using (FileStream ServerStream = new FileStream(SeverFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 1024*80, true))
   {
    byte[] buffer = new byte[length];
    ServerStream.Position = start;
    //ServerStream.Seek(start, SeekOrigin.Begin);
    ServerStream.Read(buffer, 0, length);
    return buffer;
   }
  }
 }
}

二、討論     

1)需要注意的是第44行,不能直接使用index變量在Task()里進(jìn)行操作,而是要將它賦給Threadindex,讓Threadindex在Task()里,不然會直接報(bào)錯,為什么呢?查看鏈接

2)70至108行代碼可以在外面再套一層while循環(huán),循環(huán)檢測臨時文件是否下完整了,然后再定義一個檢測最大上限,超過這個上限就放棄本次更新,當(dāng)用戶的網(wǎng)絡(luò)恢復(fù)正常后下次再做更新操作。所以說放臨時文件的文件夾最好要包含版本信息,不會把2.0.0的臨時文件和1.0.0的臨時文件搞混。

3) FileStream.Position 與 FileStream.Seek(long offset, SeekOrigin seekorigin) 的作用都是獲取流的指針位置,當(dāng)文件路徑使用絕對路徑時使用Position;相對路徑時使用Seek方法,查看鏈接

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。

上一篇:C# 編譯生成dll文件供程序調(diào)用的兩種方法

欄    目:C#教程

下一篇:c#可以創(chuàng)建任意控件的拖動方法

本文標(biāo)題:C# FileStream實(shí)現(xiàn)多線程斷點(diǎn)續(xù)傳

本文地址:http://mengdiqiu.com.cn/a1/C_jiaocheng/5241.html

網(wǎng)頁制作CMS教程網(wǎng)絡(luò)編程軟件編程腳本語言數(shù)據(jù)庫服務(wù)器

如果侵犯了您的權(quán)利,請與我們聯(lián)系,我們將在24小時內(nèi)進(jìn)行處理、任何非本站因素導(dǎo)致的法律后果,本站均不負(fù)任何責(zé)任。

聯(lián)系QQ:835971066 | 郵箱:835971066#qq.com(#換成@)

Copyright © 2002-2020 腳本教程網(wǎng) 版權(quán)所有