none
异步读写本地磁盘文件 RRS feed

  • 问题

  • Windows本身的复制、粘贴操作,在二个盘间进行大文件复制或转移时,如果目标盘的写入速度太慢,会异致操作占用大量的内存,及至虚拟内存。于是考虑自己写个可以自己控制内存占用的小程序用用。

    本来是用同步的,但同步的太占CPU,并且很奇怪的不能自己控制内存的占用。于是想用异步,但在进行异步不知道怎么控制异步读写的“继续”,在我写的代码里,CallBack只被执行一次,就再不被激发了。很奇怪。

        struct Block { internal long offset; internal int count;}
        struct DataBlock { internal Block block; internal byte[] data;}
    
        IAsyncResult iarRead, iarWrite;
    
        int iBufferSize = GlobalData.ConstantVaries.iMega * 4;//默认每次读取4M的数据
        int iBufferTimes = GlobalData.ConstantVaries.iEight;//默认读四次
    
        private void Conductor()
        {
          if (queueBlock.Count > GlobalData.ConstantVaries.iZero && queueDataBlock.Count < iBufferTimes)
          {
            bool blCanRead = (iarRead == null);
            if (!blCanRead) blCanRead = iarRead.IsCompleted;
            if (blCanRead && queueBlock.Count > GlobalData.ConstantVaries.iZero && queueDataBlock.Count < iBufferTimes)
            {
              DataBlock dbT = new DataBlock();
              dbT.data = new byte[iBufferSize];
              dbT.block = queueBlock.Dequeue();
              fsSource.Seek(dbT.block.offset, System.IO.SeekOrigin.Begin);
              iarRead = fsSource.BeginRead(dbT.data, GlobalData.ConstantVaries.iZero, dbT.block.count, new AsyncCallback(ReadCallback), dbT);
              //Console.WriteLine(queueBlock.Count);
            }
          }
          if (queueDataBlock.Count > GlobalData.ConstantVaries.iZero)
          {
            
          }
          else
          {
            
          }
        }
    
        private void ReadCallback(IAsyncResult result)
        {
          DataBlock dbT = (DataBlock)result.AsyncState;
          queueDataBlock.Enqueue(dbT);
          Console.WriteLine(queueDataBlock.Count);
          Conductor();
        }
    
        /// <summary>
        /// 开始异步复制文件
        /// </summary>
        internal void BeginCopyFile()
        {
          Conductor();
        }
    
    2011年1月18日 3:40

答案

  • dear
    1.FileStream.Read()和FileStream.Write()这两个方法搭配IAsyncResult也可以写成异步。
    2.有试过用BufferedStream或MemoryStream 或吗?

    [C#.NET][VB.NET]如何 讀寫 二進位 圖檔
    http://www.dotblogs.com.tw/yc421206/archive/2009/10/27/11312.aspx

    [C#.NET][VB.NET] 使用 BufferedStream 複製檔案
    http://www.dotblogs.com.tw/yc421206/archive/2009/10/28/11324.aspx


    3.上面两个同步方法你可以搭配IAsyncResult改成异步方法。


    [Thread] 非同步作業 IAsyncResult / AsyncCallback
    http://www.dotblogs.com.tw/yc421206/archive/2011/01/03/20540.aspx

    [C#] 將同步方法改寫為非同步方法
    http://www.dotblogs.com.tw/kirkchen/archive/2010/12/28/20435.aspx
    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/
    2011年1月19日 16:14

全部回复

  • dear
    不清楚你讲的继续是代表啥意义,使用异步并的主要原因是为了不要让主线程城绪塞车,造成UI画面卡死,你所谓CPU会标高因该是主线程,卡死在复制、贴上动作,有关异步操作,你可参考小弟的文章

    [Thread] 非同步作業 IAsyncResult / AsyncCallback
    http://social.msdn.microsoft.com/Forums/zh-CN/visualcshartzhchs/threads

    请问一下,为啥ReadCallback()又要再呼叫Conductor(),这样停不下来的结果是做啥用的?
    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/
    2011年1月18日 5:12
  • Conductor()的作用就是起调度作用。

    当自定义缓冲区未满并且源文件还没读完,就继续读。

    当自定义缓冲区有数据,就继续写。

    当源文件已经读完并且自定义缓冲区没有数据并且fsSource不在读,复制完成。

    2011年1月18日 8:16
  • 先把大文件切成一小块一小块,然后用异步逐块逐块复制过去。。浪费点 CPU。
    学习学习....
    2011年1月18日 9:53
  • 先把大文件切成一小块一小块,然后用异步逐块逐块复制过去。。浪费点 CPU。
    学习学习....


    你说的我要做的有一点点区别。

    我是切成一块一块,然后读和写都是异步进行。通过Conductor()调度控制缓存的使用。

    但现在没法进行下去。

    后来我又尝试调用EndRead(),但老出错。现在不知道怎么办。

    2011年1月19日 8:42
  • Windows本身的复制、粘贴操作,在二个盘间进行大文件复制或转移时,如果目标盘的写入速度太慢,会异致操作占用大量的内存,及至虚拟内存。于是考虑自己写个可以自己控制内存占用的小程序用用。

    本来是用同步的,但同步的太占CPU,并且很奇怪的不能自己控制内存的占用。于是想用异步,但在进行异步不知道怎么控制异步读写的“继续”,在我写的代码里,CallBack只被执行一次,就再不被激发了。很奇怪。


    补充下,我说的“同步”只是指FileStream.Read()和FileStream.Write()这二个方法。二这个方法分别在二个Thread里循环调用。
    2011年1月19日 14:17
  • dear
    1.FileStream.Read()和FileStream.Write()这两个方法搭配IAsyncResult也可以写成异步。
    2.有试过用BufferedStream或MemoryStream 或吗?

    [C#.NET][VB.NET]如何 讀寫 二進位 圖檔
    http://www.dotblogs.com.tw/yc421206/archive/2009/10/27/11312.aspx

    [C#.NET][VB.NET] 使用 BufferedStream 複製檔案
    http://www.dotblogs.com.tw/yc421206/archive/2009/10/28/11324.aspx


    3.上面两个同步方法你可以搭配IAsyncResult改成异步方法。


    [Thread] 非同步作業 IAsyncResult / AsyncCallback
    http://www.dotblogs.com.tw/yc421206/archive/2011/01/03/20540.aspx

    [C#] 將同步方法改寫為非同步方法
    http://www.dotblogs.com.tw/kirkchen/archive/2010/12/28/20435.aspx
    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/
    2011年1月19日 16:14
  • 虽然得不到我要的,还是马马虎虎结贴算了。
    2011年1月20日 5:37