zoukankan      html  css  js  c++  java
  • 异步文件IO的应用

      最近项目中大量运用xml和静态页来做缓存碎片,好处嘛有二:
    1、文件碎片的过期比较灵活,不由计划任务调度,而是由访客决定何时过期,这样冷门页面自然就不用劳系统的神进行更新;
    2、较之静态页,采用缓存文件碎片+动态页方式,能更加灵活地实现功能的控制,诸如一些小功能的更改。

      但经过压力测试,发现同步的文件I/O,在并发过大的情况下,经常会出现锁文件的异常,颇让人头疼

      只有借助异步I/O来解决了,在网上找来了一个功能较完备的工具集代码族,如下:
    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 IndieFacade
    {
        
    /// <summary>
        
    /// 异步完成事件
        
    /// </summary>

        public class ReadLargeFileCompletedEventArgs : AsyncCompletedEventArgs
        
    {
            
    byte[] _buffer;
            
    public byte[] Buffer
            
    {
                
    get return _buffer; }
            }

            
    public ReadLargeFileCompletedEventArgs(byte[] buffer, Exception e, bool canncel, object state)
                : 
    base(e, canncel, state)
            
    {
                _buffer 
    = buffer;
            }

        }

        
    /// <summary>
        
    /// 异步执行进度
        
    /// </summary>

        public class ReadLargeFileProgressEventArgs : ProgressChangedEventArgs
        
    {
            
    int _FileLen;
            
    int _Reads;
            
    byte[] buffer;
            
    public ReadLargeFileProgressEventArgs(int iFileLength, int iHasRead, int Percentage, object state, byte[] _Buffer)
                :
                
    base(Percentage, state)
            
    {
                _FileLen 
    = iFileLength;
                _Reads 
    = iHasRead;
                buffer 
    = _Buffer;

            }

            
    public int FileLength
            
    {
                
    get return _FileLen; }
            }

            
    public int HasRead
            
    {
                
    get return _Reads; }
            }

            
    public byte[] Buffer
            
    {
                
    get return buffer; }
            }

        }

        
    /// <summary>
        
    /// 读取完成完成
        
    /// </summary>    

        public delegate void ReadLargeFileCompletedEventHander(object sender, ReadLargeFileCompletedEventArgs e);
        
    /// <summary>
        
    /// 进度改变
        
    /// </summary>    

        public delegate void ReadLargeFileProgressEventHandler(object sender, ReadLargeFileProgressEventArgs e);

        
    /// <summary>
        
    /// 异步数据访问
        
    /// </summary>

        public class AsyncDataAccess
        
    {
            
    internal delegate void WorkerEventHander(string sFilePath, object userToken);

            
    public event ReadLargeFileCompletedEventHander ReadCompleted;
            
    public event ReadLargeFileProgressEventHandler ReadProgressChanged;

            HybridDictionary taskToker 
    = new HybridDictionary();

            SendOrPostCallback _complated;
            SendOrPostCallback _reportProgress;
            SendOrPostCallback _completionMethod;
            
    protected void OnReadCompleted(ReadLargeFileCompletedEventArgs args)
            
    {
                
    if (ReadCompleted != null)
                    ReadCompleted(
    this, args);
            }

            
    protected void OnReadProgressChanged(ReadLargeFileProgressEventArgs args)
            
    {
                
    if (ReadProgressChanged != null)
                    ReadProgressChanged(
    this, args);
            }


            
    public AsyncDataAccess()
            
    {
                _complated 
    = new SendOrPostCallback(comleted);
                _reportProgress 
    = new SendOrPostCallback(report);
                _completionMethod 
    = new SendOrPostCallback(completionMethod);
            }

            
    void comleted(object state)
            
    {
                ReadLargeFileCompletedEventArgs args 
    = state as ReadLargeFileCompletedEventArgs;
                OnReadCompleted(args);

            }

            
    void report(object state)
            
    {
                ReadLargeFileProgressEventArgs args 
    = state as ReadLargeFileProgressEventArgs;
                OnReadProgressChanged(args);
            }


            
    void completionMethod(object state)
            
    {

                AsyncDataAccessState ad 
    = (AsyncDataAccessState)state;
                AsyncOperation asyncOp 
    = ad.AsyncOp;

                ReadLargeFileCompletedEventArgs a 
    = new ReadLargeFileCompletedEventArgs(ad.FileContent, nullfalse, ad.TaskID);

                
    lock (taskToker.SyncRoot)
                
    {
                    taskToker.Remove(asyncOp.UserSuppliedState);
                }

                asyncOp.PostOperationCompleted(_complated, a);
            }


            
    public void ReadLargeFile(string sFilePath, long iTaskID)
            
    {
                WorkerEventHander weh 
    = new WorkerEventHander(read);
                AsyncOperation op 
    = AsyncOperationManager.CreateOperation(iTaskID);
                
    lock (taskToker.SyncRoot)
                
    {
                    
    if (!taskToker.Contains(iTaskID))
                    
    {
                        taskToker.Add(iTaskID, op);

                        FileInfo fi 
    = new FileInfo(sFilePath);
                        AsyncDataAccessState dast 
    = new AsyncDataAccessState(op, iTaskID, (int)fi.Length, weh, new byte[(int)fi.Length]);
                        
    采用回调方式的做法
                        
    不采用回调方式时的做法
                    }

                }


            }

            
    void callback(IAsyncResult ar)
            
    {

                AsyncDataAccessState state 
    = (AsyncDataAccessState)ar.AsyncState;
                WorkerEventHander weh 
    = state.Worker;
                weh.EndInvoke(ar);
                ReadLargeFileCompletedEventArgs args 
    = new ReadLargeFileCompletedEventArgs(state.FileContent, nullfalse, state.TaskID);
                _complated(args);
            }



            
    public void CancelAsync(int taskId)
            
    {
                
    lock (taskToker.SyncRoot)
                
    {
                    
    object obj = taskToker[taskId];
                    
    if (obj != null)
                    
    {
                        AsyncOperation asyncOp 
    = obj as AsyncOperation;
                        ReadLargeFileCompletedEventArgs args 
    = new ReadLargeFileCompletedEventArgs(
                            
    nullnulltrue, taskId);
                        _complated(args);
                    }

                }

            }


            
    private void read(string sFilepath, object userToken)
            
    {
                AsyncDataAccessState st 
    = (AsyncDataAccessState)userToken;
                FileStream fs 
    = new FileStream(sFilepath, FileMode.Open, FileAccess.Read, FileShare.Read, 0x1000true);
                
    byte[] buffer = new byte[0x1000];
                
    int res = fs.Read(buffer, 00x1000);
                
    int cnt = 0;
                
    while (res > 0)
                
    {
                    cnt 
    += res;
                    
    byte[] cf = new byte[res];
                    
    for (int i = 0; i < res; i++)
                        cf[i] 
    = buffer[i];
                    
    //lock (st.FileContent.SyncRoot)
                    
    //{
                    cf.CopyTo(st.FileContent, 0);
                    
    //}
                    int pctn = (int)((float)cnt / (float)st.FileLen * 100);

                    ReadLargeFileProgressEventArgs args 
    = new ReadLargeFileProgressEventArgs(st.FileLen, cnt, pctn, st.TaskID, cf);
                    
    //Console.WriteLine("read" + cnt.ToString());
                    this._reportProgress(args);//-----------A
                    异步发送ChangedEvent,不保证发送的顺序,与A点是互斥的
                    res 
    = fs.Read(buffer, 00x1000);
                }

                fs.Close();
                
    不采用回调方式时的做法


            }

            
    /// <summary>
            
    /// 异步数据访问状态类
            
    /// </summary>

            internal class AsyncDataAccessState
            
    {
                
    public AsyncOperation AsyncOp;
                
    public long TaskID;
                
    public int FileLen;
                
    public WorkerEventHander Worker;
                
    public Byte[] FileContent;
                
    public AsyncDataAccessState(AsyncOperation op, long iTaskID, int iFileLen, WorkerEventHander workerDelete, Byte[] _FileContent)
                
    {
                    FileContent 
    = _FileContent;
                    AsyncOp 
    = op;
                    TaskID 
    = iTaskID;
                    FileLen 
    = iFileLen;
                    Worker 
    = workerDelete;
                }

            }

        }

    }

      这里稍进行了一点改动,将标识ID(即userToken)改为了long型,在页面级别应用时,可直接将一个时间Ticks塞入以进行标识,如果这还不够,那就相当寸了,但也不坏,至少能读出东西来

      据MSDN的说法,要应用异步IO功能,必须将Page的异步模式开关打开,即在页头这样写 <%@ Page sync="true"...,然后,异步代码族的调用必须在OnPreRender(EventArgs e)事件之前(含)调用,那么就可以这么写:
        protected override void OnPreRender(EventArgs e)
        
    {
            
    base.OnPreRender(e);
            
    // 功能处理
            if (Request.QueryString["id"== null)
                
    return;
            
    // 传递的艺人ID
            this.artId = Convert.ToInt32(Request.QueryString["id"]);
            
    // 获取信息
            GenStaticHtml();
        }


     
    // ---------------------------  生成方法 ------------------------------- //

        
    /// <summary>
        
    /// 生成静态页
        
    /// </summary>    

        void GenStaticHtml()

        
    // ---------------------------  异步事件 ------------------------------- //
        protected void da_ReadCompleted(object sender, ReadLargeFileCompletedEventArgs e)
        
    {
            
    long id = (long)e.UserState;
            
    if (id == tid)
            
    {
                Response.Write(Encoding.UTF8.GetString(e.Buffer, 
    0, e.Buffer.Length));
                Response.Flush();
                Response.End();
            }

        }
  • 相关阅读:
    Django实现自定义template页面并在admin site的app模块中加入自定义跳转链接(一)
    yaml中的锚点和引用
    Kafka查看topic、consumer group状态命令
    手把手教你写一个脚手架
    可视化拖拽组件库一些技术要点原理分析(三)
    《带你入门前端工程》开源了
    可视化拖拽组件库一些技术要点原理分析(二)
    实验 7: OpenDaylight 实验——Python 中的 REST API 调用
    实验 6:OpenDaylight 实验——OpenDaylight 及 Postman 实现流表下发
    实验 5:OpenFlow 协议分析和 OpenDaylight 安装
  • 原文地址:https://www.cnblogs.com/moye/p/942231.html
Copyright © 2011-2022 走看看