using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Threading; using System.ComponentModel; namespace ExtensionTest { public class Async : IDisposable { private bool suspend; private bool cancel; private Stream readStream; private Stream writeSteam; private AutoResetEvent auto; public long TotalLength { get; private set; } private AsyncOperation asyncOperation; public bool Suspend { get { return this.suspend; } set { if (this.suspend && !value && !this.auto.SafeWaitHandle.IsClosed) auto.Set(); this.suspend = value; } } public bool Cancel { get { return cancel; } set { cancel = value; } } public event EventHandler<ReportEventArgs> ProgressReport; public Async() { asyncOperation = AsyncOperationManager.CreateOperation(null); auto = new AutoResetEvent(true); } /// <summary> /// 初始化读写流 /// </summary> /// <param name="fileToRead">用来读取的文件名</param> /// <param name="fileToWrite">用来保存的文件名</param> private void InitStream(string fileToRead, string fileToWrite) { if (!File.Exists(fileToRead)) { throw new ArgumentException(); } FileInfo info = new FileInfo(fileToRead); //文件大小 this.TotalLength = info.Length; /* * 根据文件大小选择选择读取和写入文件的策略 * 如果大于某个值就构造异步流 */ //if (info.Length > 10 * 1024 * 1024) //{ // readStream = new FileStream(fileToRead, FileMode.Open, FileAccess.Read, FileShare.Read, 1024, // FileOptions.Asynchronous); //} //else readStream = info.Open(FileMode.Open, FileAccess.Read, FileShare.Read); writeSteam = File.Open(fileToWrite, FileMode.Create, FileAccess.Write, FileShare.Write); } /// <summary> /// 使用迭代器开始异步操作 /// </summary> /// <param name="fileToRead">用来读取的文件名</param> /// <param name="fileToWrite">用来保存的文件名</param> public void StartAsyncOperationWithIterator(string fileToRead, string fileToWrite) { this.InitStream(fileToRead, fileToWrite); ThreadPool.QueueUserWorkItem(arg => { byte[] buffer = new byte[1024]; IEnumerator<int> enumerator = ReadBytes(buffer); while (enumerator.MoveNext()) { if (this.suspend && !auto.SafeWaitHandle.IsClosed) auto.WaitOne(); this.asyncOperation.Post(obj => this.OnReportProgress(enumerator.Current), null); /* *如果是Thread.Sleep(0)由于消息发送太快 接收进度报告的窗体也呈假死状态 * 而如果是Thread.Sleep(1)则会影响读写速度 惆怅 */ Thread.Sleep(1); } }); } private IEnumerator<int> ReadBytes(byte[] buffer) { try { int readLength = readStream.Read(buffer, 0, buffer.Length); while (readLength > 0) { writeSteam.Write(buffer, 0, readLength); yield return readLength; if (this.cancel) { this.Dispose(); yield break; } readLength = readStream.Read(buffer, 0, buffer.Length); } } finally { this.Dispose(); } } /// <summary> /// 开始异步操作 /// </summary> /// <param name="fileToRead">用来读取的文件名</param> /// <param name="fileToWrite">用来保存的文件名</param> public void StartAsyncOperation(string fileToRead, string fileToWrite) { this.StartAsyncOperation(fileToRead, fileToWrite, null); } /// <summary> /// 开始异步操作 /// </summary> /// <param name="fileToRead">用来读取的文件名</param> /// <param name="fileToWrite">用来保存的文件名</param> /// <param name="completed">完成读写操作后的回调方法</param> public void StartAsyncOperation(string fileToRead, string fileToWrite, Action<Exception> completed) { this.StartAsyncOperation(fileToRead, fileToWrite, null, completed); } /// <summary> /// 开始异步操作 /// </summary> /// <param name="fileToRead">用来读取的文件名</param> /// <param name="fileToWrite">用来保存的文件名</param> /// <param name="cancelAction">取消时的回调方法</param> /// <param name="completed">完成读写操作后的回调方法</param> public void StartAsyncOperation(string fileToRead, string fileToWrite, Action cancelAction, Action<Exception> completed) { this.StartAsyncOperation(fileToRead, fileToWrite, null, cancelAction, completed); } /// <summary> /// 开始异步操作 /// </summary> /// <param name="fileToRead">用来读取的文件名</param> /// <param name="fileToWrite">用来保存的文件名</param> /// <param name="suspendAction">暂停时的回调方法</param> /// <param name="cancelAction">取消时的回调方法</param> /// <param name="completed">完成读写操作后的回调方法</param> public void StartAsyncOperation(string fileToRead, string fileToWrite, Action<bool> suspendAction, Action cancelAction, Action<Exception> completed) { this.StartAsyncOperation(fileToRead, fileToWrite, null, suspendAction, cancelAction, completed); } /// <summary> /// 开始异步操作 /// </summary> /// <param name="fileToRead">用来读取的文件名</param> /// <param name="fileToWrite">用来保存的文件名</param> /// <param name="timeOutAction">超时时调用的方法(只有支持超时的流才会回调)</param> /// <param name="suspendAction">暂停时的回调方法</param> /// <param name="cancelAction">取消时的回调方法</param> /// <param name="completed">完成读写操作后的回调方法</param> public void StartAsyncOperation(string fileToRead, string fileToWrite, Action<Operation> timeOutAction, Action<bool> suspendAction, Action cancelAction, Action<Exception> completed) { this.InitStream(fileToRead, fileToWrite); if (readStream == null || writeSteam == null) return; byte[] buffer = new byte[1024]; AsyncCallback callback = null; callback = readResult => { int readLength = readStream.EndRead(readResult); if (readLength > 0) { writeSteam.BeginWrite(buffer, 0, readLength, writeResult => { try { writeSteam.EndWrite(writeResult); //降低cpu使用率 Thread.Sleep(0); OnReportProgress(readLength); //暂停 if (this.suspend && !this.auto.SafeWaitHandle.IsClosed) { if (suspendAction != null) suspendAction(true); this.auto.WaitOne(); } //取消 if (cancel) { this.Dispose(); if (cancelAction != null) asyncOperation.Post(obj => cancelAction(), null); return; } readStream.BeginRead(buffer, 0, buffer.Length, callback, null); } catch (Exception ex) { Dispose(); if (completed != null) asyncOperation.Post(obj => completed(ex), null); } }, null); } else { Dispose(); if (completed != null) asyncOperation.Post(obj => completed(null), null); } }; readStream.BeginRead(buffer, 0, buffer.Length, callback, null); } private void Dispose() { readStream.Close(); readStream.Dispose(); writeSteam.Close(); writeSteam.Dispose(); } private void OnReportProgress(int readLength) { if (this.ProgressReport != null) { ReportEventArgs args = new ReportEventArgs(readLength, this.TotalLength); //发送完成进度报告 asyncOperation.Post(obj => this.ProgressReport(null, args), null); } } void IDisposable.Dispose() { auto.Close(); } } public enum Operation { Read, Write } public class ReportEventArgs : EventArgs { public long CompletedLength { get; private set; } public long TotalLength { get; private set; } public ReportEventArgs(long completedLength, long totalLength) { this.CompletedLength = completedLength; this.TotalLength = totalLength; } } }
转载于:https://www.cnblogs.com/DreamWork/archive/2009/07/02/1515871.html