的改进版。功能上更简洁一些,不过对同时访问同一个文件的互斥操作还没做好。
其改进主要是以下几点:
一: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;
}
}
}
}