最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2018年03月22日 11:28:58   作者:airforce094  
這篇文章主要為大家詳細(xì)介紹了C# FileStream實(shí)現(xiàn)多線程斷點(diǎn)續(xù)傳,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

一、前言

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

代碼如下:

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ù)包個(gè)數(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()里的絕對(duì)不能直接使用index
    var task = new Task(() =>
    {
     string tempfilepath = @"E:\Test\TestFile\Temp\" + "QS_" + Threadindex + "_" + PackCount; //臨時(shí)文件路徑

     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");


   //檢測(cè)有哪些數(shù)據(jù)包未下載
   Console.WriteLine("Start Compare");
   DirectoryInfo TempDir = new DirectoryInfo(@"E:\Test\TestFile\temp"); //臨時(shí)文件夾路徑
   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)備將臨時(shí)文件融合并寫(xiě)到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");



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


  //這個(gè)方法可以放到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()里,不然會(huì)直接報(bào)錯(cuò),為什么呢?查看鏈接

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

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

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Task提高異步執(zhí)行效率技巧

    Task提高異步執(zhí)行效率技巧

    這篇文章介紹了Task提高異步執(zhí)行效率的技巧,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • C#多線程系列之任務(wù)基礎(chǔ)(一)

    C#多線程系列之任務(wù)基礎(chǔ)(一)

    本文詳細(xì)講解了C#多線程的任務(wù)基礎(chǔ),文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02
  • C#引用類(lèi)型轉(zhuǎn)換的常見(jiàn)方式總結(jié)

    C#引用類(lèi)型轉(zhuǎn)換的常見(jiàn)方式總結(jié)

    這篇文章主要介紹了C#引用類(lèi)型轉(zhuǎn)換的常見(jiàn)方式,包括子類(lèi)轉(zhuǎn)換成父類(lèi),父類(lèi)轉(zhuǎn)換成子類(lèi),以及不是子父級(jí)關(guān)系類(lèi)之間的轉(zhuǎn)換,需要的朋友可以參考下
    2014-09-09
  • C# 運(yùn)算符 ?、??、?: 各種問(wèn)號(hào)的用法和說(shuō)明

    C# 運(yùn)算符 ?、??、?: 各種問(wèn)號(hào)的用法和說(shuō)明

    本文介紹C#中三種常見(jiàn)的問(wèn)號(hào)運(yùn)算符的使用方法,簡(jiǎn)單講解給大家,希望對(duì)大家有所幫助。
    2016-04-04
  • Unity 點(diǎn)擊UI與點(diǎn)擊屏幕沖突的解決方案

    Unity 點(diǎn)擊UI與點(diǎn)擊屏幕沖突的解決方案

    這篇文章主要介紹了Unity 點(diǎn)擊UI與點(diǎn)擊屏幕沖突的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • C#中的LINQ?to?Objects詳解(2)

    C#中的LINQ?to?Objects詳解(2)

    本文詳細(xì)講解了C#中的LINQ?to?Objects,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • C#中的 == 和equals()區(qū)別淺析

    C#中的 == 和equals()區(qū)別淺析

    這篇文章主要介紹了C#中的 == 和equals()的區(qū)別,對(duì)不同點(diǎn)進(jìn)行了闡述,感興趣的小伙伴們可以參考一下
    2015-11-11
  • C#跨窗體操作(引用傳遞) 實(shí)例代碼

    C#跨窗體操作(引用傳遞) 實(shí)例代碼

    現(xiàn)在給大家介紹一種最簡(jiǎn)單的跨窗體操作,WinForm的窗體是一個(gè)類(lèi),C#的類(lèi)是引用類(lèi)型,那么我們應(yīng)該可以將WinForm窗體類(lèi)進(jìn)行傳遞,那不就可以進(jìn)行操作了么?
    2013-03-03
  • C#中實(shí)現(xiàn)AES算法加密解讀

    C#中實(shí)現(xiàn)AES算法加密解讀

    這篇文章主要介紹了C#中實(shí)現(xiàn)AES算法加密實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • c#中判斷字符串是不是數(shù)字或字母的方法

    c#中判斷字符串是不是數(shù)字或字母的方法

    這篇文章介紹了C#判斷字符串是否數(shù)字或字母的實(shí)例,有需要的朋友可以參考一下
    2013-06-06

最新評(píng)論

莒南县| 宜兰市| 田阳县| 安泽县| 图片| 尖扎县| 聊城市| 舒兰市| 普定县| 嘉善县| 黄大仙区| 临朐县| 家居| 台江县| 新乡县| 礼泉县| 哈密市| 基隆市| 屯门区| 皮山县| 湄潭县| 诸暨市| 托克逊县| 西青区| 大姚县| 图木舒克市| 石屏县| 丹巴县| 蚌埠市| 桐庐县| 交城县| 南岸区| 霍邱县| 鹤庆县| 类乌齐县| 尼玛县| 太保市| 石台县| 桂阳县| 梁河县| 天祝|