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

王朝c#·作者佚名  2006-12-17
宽屏版  字体: |||超大  

方式一:一次获取,异步写入

/// <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();

}

}

两种方式的比较:

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

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

其中:两种方式的异步机制都是相同的,没有任何区别;异步机制的优点在于充分发挥了操作系统的优点

注意:在需要对性能进行同比测试的上下文中不能采用异步机制而必须尽量采用同步机制,以提高真实性

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
© 2005- 王朝网络 版权所有