异步读取大文件的改进

    这个是异步读取大文件
的改进版。功能上更简洁一些,不过对同时访问同一个文件的互斥操作还没做好。 

其改进主要是以下几点:

一:FileStream.Read的调用改为BeginRead,

二:报告进度的方法挪到BeginRead的回调方法之中。

三:在异步读取完成或是取消异步读取时,关闭文件流。

四:每次读取的内容放在读取进度报告之中,并记录下当前已读取了多少,及开始读取的位置。

五:由于是大文件,因此,在读取完成的事件参数里不记录读取内容。只记录完成时的时间。

经过总结发现,异步读取对小文件(小于1M)不起作用,还不如用File.ReadAllText来的快,只有在文件大于100M时效果比较明显.不太清楚是什么原因,可能是异步调用时线程切换比较费时吧!

下面是源码。有空的话做成教学课件放到自己的在线教育网站上请各位指点一下。

using System;
using System.Collections.Generic;
using System.Text;
using System.Data ;
using System.Data.SqlClient ;
using System.Threading ;
using System.ComponentModel ;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
 
namespace AsyncIO.FileIO
{
    public class ReadBLOBFileCompletedEventArgs : AsyncCompletedEventArgs
    {
        public FileStream FS;
        public ReadBLOBFileCompletedEventArgs(FileStream fs ,Exception e,bool canncel,object state)
            : base(e, canncel, state)
        {
            FS = fs;
        }
    }
    public class ReadBLOBFileProgressEventArgs : ProgressChangedEventArgs
    {
      
        byte[] buffer;
        public ReadBLOBFileProgressEventArgs(int Percentage, object state,byte[] _Buffer)
            : base(Percentage, state)
        {
          
            buffer = _Buffer;

        }
     
        public byte[] Buffer
        {
            get { return buffer; }
        }
    }
    public delegate void ReadBLOBFileCompletedEventHander(object sender, ReadBLOBFileCompletedEventArgs e);
    public delegate void ReadBLOBFileProgressEventHandler(object sender ,ReadBLOBFileProgressEventArgs e);
   
  
    
    public class AsyncReadWriteLargeFile
    {
        private delegate void ReadBLOBFileWorker(FileStream fs, object userToken);

        public event ReadBLOBFileCompletedEventHander ReadBLOBFileCompleated;
        public event ReadBLOBFileProgressEventHandler ReadBLOBFileProgressChanged;
        #region Fire Event
        protected virtual void OnReadBLOBFileCompleated(ReadBLOBFileCompletedEventArgs args)
        {
            if (ReadBLOBFileCompleated != null)
                ReadBLOBFileCompleated(this, args);
        }
        protected virtual void OnReadBLOBFileProgressChanged(ReadBLOBFileProgressEventArgs args)
        {
            if (ReadBLOBFileProgressChanged != null)
                ReadBLOBFileProgressChanged(this, args);
        }
        #endregion

        SendOrPostCallback _completed;
        SendOrPostCallback _report;
        HybridDictionary _task = new HybridDictionary();
     
        #region SendOrPostCallback Function
        void compeleted(object state)
        {
            ReadBLOBFileCompletedEventArgs e = state as ReadBLOBFileCompletedEventArgs;
            e.FS.Close();
            OnReadBLOBFileCompleated(e);
        }
        void report(object state)
        {
            ReadBLOBFileProgressEventArgs e = state as ReadBLOBFileProgressEventArgs;
            OnReadBLOBFileProgressChanged(e);
        }
        #endregion

        void Init()
        {
            _completed = new SendOrPostCallback(compeleted);
            _report = new SendOrPostCallback(report);
        }
        public AsyncReadWriteLargeFile()
        {
            Init();
        }
        public void CancelAsync(Guid id)
        {
            BLOBFileState op = _task[id] as BLOBFileState;
            if (op != null)
            {
                ReadBLOBFileCompletedEventArgs e = new ReadBLOBFileCompletedEventArgs(op.FS, null, true, id);
                op.AsyncOp.PostOperationCompleted(_completed, e);
                lock (_task.SyncRoot)
                {
                    _task.Remove(id);
                }
            }
        }
        public void ReadAsync(string xmlFile,Guid id)
        {
          
            ReadBLOBFileWorker work = new ReadBLOBFileWorker(worker);
            AsyncOperation op = AsyncOperationManager.CreateOperation(id);
            lock (_task.SyncRoot)
            {
                if(_task.Contains(id)==false )
                {
                    FileStream fs = new FileStream(xmlFile, FileMode.Open);
                    BLOBFileState st = new BLOBFileState(fs,op);
                    _task.Add(id, st);
                    work.BeginInvoke(fs, st, null, null);
                }
            }
          
        }
    
        void worker(FileStream fs, object userToken)
        {
            BLOBFileState st = userToken as BLOBFileState;
            AsyncOperation op = st.AsyncOp;
            BLOBFileReadBufferState rf = new BLOBFileReadBufferState(fs, new byte[0x1000],op,0);
            fs.BeginRead(rf.Buffer, 0, 0x1000, new AsyncCallback(readCallback), rf);
        }
        void readCallback(IAsyncResult  ar)
        {
            BLOBFileReadBufferState rf = ar.AsyncState as BLOBFileReadBufferState;
            int res = rf.FS.EndRead(ar);
            if (res > 0)
            {
                rf.HasRead =rf.StartPos +res ;
                float p = (float)rf.HasRead / (float)rf.FS.Length;
                int cx = (int)(p * 100);
                byte[] buffer = new byte[res];
                Array.Copy(rf.Buffer, buffer, res);
                ReadBLOBFileProgressEventArgs e = new ReadBLOBFileProgressEventArgs(cx, rf.AsyncOp.UserSuppliedState, buffer);
                this._report(e);
                BLOBFileReadBufferState bf2 = new BLOBFileReadBufferState(rf.FS, new byte[0x1000], rf.AsyncOp,rf.HasRead);
                rf.FS.BeginRead(bf2.Buffer, 0, 0x1000, new AsyncCallback(readCallback), bf2);
            }
            else
            {
                rf.FS.Close();
                ReadBLOBFileCompletedEventArgs e = new ReadBLOBFileCompletedEventArgs(rf.FS ,null, false, rf.AsyncOp.UserSuppliedState);
                rf.AsyncOp.PostOperationCompleted(this._completed, e);
                //this._completed(e);
               
            }


        }
        internal class BLOBFileReadBufferState
        {
            public FileStream FS;
            public byte[] Buffer;
            public AsyncOperation AsyncOp;
            public int StartPos;
            public int HasRead;
            public BLOBFileReadBufferState(FileStream fs, Byte[] buffer,AsyncOperation op,int startPos)
            {
                FS = fs;
                Buffer = buffer;
                AsyncOp = op;
                StartPos = startPos;
            }
        }
    

        internal class BLOBFileState
        {
            public FileStream FS;
            public AsyncOperation AsyncOp;
            public BLOBFileState(FileStream fs,  AsyncOperation asyncOp)
            {
                FS = fs;
                AsyncOp = asyncOp;

            }
        }
    }
}

posted on 2007-05-31 15:08  老代哥哥  阅读(194)  评论(0编辑  收藏  举报

导航