将数据库中二进制数据以异步方式写入磁盘

类别:.NET开发 点击:0 评论:0 推荐:

方式一:一次获取,异步写入
/// <summary>
  /// 缓冲区大小
  /// </summary>
  public const int numPixels = 512 * 512;
 /// <summary>
  /// 将数据文件写入磁盘
  /// </summary>
  /// <param name="strSql"></param>
  /// <returns></returns>
  public static bool  MakeFileWithWriteListByAdapter(string strSql,out string strErr)
  {
   if(File.Exists(ConfigProxy.GetValueByKey("ListFile")))File.Delete(ConfigProxy.GetValueByKey("ListFile"));
   DataTable objTable;    
   if(!OleDataBaseProxy.ExecuteSql(strSql,out objTable,out strErr))return false;
   string outputPath = ConfigProxy.GetValueByKey("OutputPath");
   if(objTable.Rows.Count < 1) return false;  
   string strDirectory = outputPath + "\\";
   if(!Directory.Exists(strDirectory)) Directory.CreateDirectory(strDirectory);
   for(int i = 0;i< objTable.Rows.Count; i ++)
   {
    
    string fileName = objTable.Rows[i]["附件名称"].ToString();
    //记录输出列表
    LogProxy.WriteList(strDirectory + fileName);
    //获取文件数据
    byte [] ImageContent = (byte[])objTable.Rows[i]["附件内容"];    
    AutoResetEvent manualEvent = new AutoResetEvent(false);   
    FileStream fStream =
     new FileStream(strDirectory + fileName,FileMode.Create,
     FileAccess.ReadWrite, FileShare.None, 4096, true);   
    IAsyncResult asyncResult = fStream.BeginWrite(
     ImageContent, 0, ImageContent.Length,
     new AsyncCallback(EndWriteCallback),
     new State(fStream, manualEvent));   
    manualEvent.WaitOne(5000, false);
    fStream.Close();
   }
   strErr = "";
   return true;
  } 
class State
  {
   public FileStream fStream;
   public AutoResetEvent autoEvent;

   public State(FileStream fStream, AutoResetEvent autoEvent)
   {
    this.fStream   = fStream;
    this.autoEvent = autoEvent;
   }
  }
  static void EndWriteCallback(IAsyncResult asyncResult)
  {

   State stateInfo = (State)asyncResult.AsyncState;
   int workerThreads;
   int portThreads;
   try
   {
    ThreadPool.GetAvailableThreads(out workerThreads,
     out portThreads);   
    stateInfo.fStream.EndWrite(asyncResult);    
    Thread.Sleep(1500);
   }
   finally
   {    
    stateInfo.autoEvent.Set();
   }
  }

方式二:联机读取,异步写入

/// <summary>
  /// 缓冲区大小
  /// </summary>
  public const int numPixels = 512 * 512;
/// <summary>
  /// 将数据文件写入磁盘
  /// </summary>
  /// <param name="strSql"></param>
  /// <returns></returns>
  public static bool  MakeFileWithWriteListByReader(string strSql,out string strErr)
  { 
   if(File.Exists(ConfigProxy.GetValueByKey("ListFile")))File.Delete(ConfigProxy.GetValueByKey("ListFile"));
   string outputPath = ConfigProxy.GetValueByKey("OutputPath");
   string strDirectory = outputPath + "\\";
   if(!Directory.Exists(strDirectory)) Directory.CreateDirectory(strDirectory);
   System.Data.OleDb.OleDbCommand cmd = new OleDbCommand();
   OleDbConnection Cnn = new OleDbConnection(ConfigProxy.GetValueByKey("OleConnectionString"));
   cmd.Connection = Cnn;
   cmd.CommandText = strSql;   
   //开启连接
   try
   {
    Cnn.Open();
   }
   catch(Exception Err)
   {
    strErr = Err.Message;
    return false;
   }
   byte[] pixels = new byte[numPixels];  
   OleDbDataReader reader = cmd.ExecuteReader();
   byte[]ImageContent;
   //逐条处理
   while(reader.Read())
   {
    string fileName = reader.GetString(1);
    //记录输出列表
    LogProxy.WriteList(strDirectory + fileName);
    //获取文件数据
    ImageContent = new byte[Convert.ToInt64(reader.GetString(7))];
    reader.GetBytes(6,0,ImageContent,0,Convert.ToInt32(reader.GetString(7))); 
    AutoResetEvent manualEvent = new AutoResetEvent(false);   
    FileStream fStream =
     new FileStream(strDirectory + fileName,FileMode.Create,
     FileAccess.ReadWrite, FileShare.None, 4096, true);   
    IAsyncResult asyncResult = fStream.BeginWrite(
     ImageContent, 0, ImageContent.Length,
     new AsyncCallback(EndWriteCallback),
     new State(fStream, manualEvent));   
    manualEvent.WaitOne(5000, false);
    fStream.Close();
   }
   reader.Close();
   //关闭连接
   if(Cnn.State == System.Data.ConnectionState.Open)
   {
    Cnn.Close();
   } 
   strErr = "";
   //释放资源
   Cnn.Dispose();
   cmd.Dispose();
   GC.Collect();
   return true; 
  }
  class State
  {
   public FileStream fStream;
   public AutoResetEvent autoEvent;

   public State(FileStream fStream, AutoResetEvent autoEvent)
   {
    this.fStream   = fStream;
    this.autoEvent = autoEvent;
   }
  }
  static void EndWriteCallback(IAsyncResult asyncResult)
  {

   State stateInfo = (State)asyncResult.AsyncState;
   int workerThreads;
   int portThreads;
   try
   {
    ThreadPool.GetAvailableThreads(out workerThreads,
     out portThreads);   
    stateInfo.fStream.EndWrite(asyncResult);    
    Thread.Sleep(1500);
   }
   finally
   {    
    stateInfo.autoEvent.Set();
   }
  }

 两种方式的比较:
 
方式一:适合于数据库负载较大,二进制数据大小已知的情况;
方式二:适合于数据库负载较小,二进制数据大小未知的情况;

其中:两种方式的异步机制都是相同的,没有任何区别;异步机制的优点在于充分发挥了操作系统的优点
注意:在需要对性能进行同比测试的上下文中不能采用异步机制而必须尽量采用同步机制,以提高真实性

本文地址:http://com.8s8s.com/it/it41680.htm