Asp.net异步文件读写并发处理总结

来源:互联网 发布:mac电脑键盘清理 编辑:程序博客网 时间:2024/06/05 22:56

Asp.net异步文件读写并发处理总结

运行场景

系统在用户打开下载页面的时候异步请求,根据数据动态生成一个Word文件,并返回给页面文件的大小显示在页面上,用户在生成后可以点击下载获取生成的Word文件,不希望数据有超过5分钟的延迟。

遇到的问题

一开始很简单的写了几句代码,在本地测试通过。省去业务逻辑的代码如下

生成Word:

protected int CreateWord()

{

string strFilePath = @"D:\NewWord.docx";

 ProjectWord word = new ProjectWord();

word.Save(strFilePath);

System.IO.FileInfo file = new System.IO.FileInfo(strFilePath);

return file.Length;

}

下载Word:

Response.ContentType = "application/x-zip-compressed";

Response.AddHeader("Content-Disposition", "attachment;filename=" + Path.GetFileName(strFilePath));

Response.TransmitFile(strFilePath);

Response.Flush();

Response.End();

 

上传到服务器的时候,大量的操作就出问题了。在word.Save的时候出现了IO读写错误,想了想是文件被用户下载的时候,给占用的,读写不能同时操作,怎么办呢?

方案一

生成Word的代码:

protected int CreateWord()

{

string strFilePath = @"D:\NewWord.docx";

 

System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(() =>

{

ProjectWord word = new ProjectWord();

int i = 0;

while (i < 10)

{

try

{

word.Save(strFilePath);

}

catch

{

System.Threading.Thread.Sleep(1000);

i++;

}

}

}));

t.Start();

System.IO.FileInfo file = new System.IO.FileInfo(strFilePath);

return file.Length;

}

下载Word代码不变。

网站不在报错了,用户也能正常下载了文件,但下载出来的文件有时候不是及时的,原因太简单了,保存10次都没成功的话,就不保存了,而且并发量大的时候是几乎不会成功的。只适合小并发量的情况下使用该方法,小并发量我也不推荐,虽然我使用了这个方法顶了几个小时。

方案二:

生成Word的代码:

protected int CreateWord()

{

string strFilePath = @"D:\NewWord.docx";

lock (brCreaterAddressLock)

{

System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(() =>

{

brCreaterAddressLock.AddParticipant();

ProjectWord word = new ProjectWord();

int i = 0;

while (i <= 10)

{

try

{

word.Save(strFilePath); }

catch

{

}

finally

{

brCreaterAddressLock.RemoveParticipant();

}

}

}));

t.Start();

}

System.IO.FileInfo file = new System.IO.FileInfo(strFilePath);

return file.Length;

}

public static System.Threading.Barrier brCreaterAddressLock = new System.Threading.Barrier(0);

 

下载Word的代码:

Handler.brCreaterAddressLock.AddParticipant();

Handler.brCreaterAddressLock.SignalAndWait();

Response.ContentType = "application/x-zip-compressed";

Response.AddHeader("Content-Disposition", "attachment;filename=" + Path.GetFileName(strFilePath));

Response.TransmitFile(strFilePath);

Response.Flush();

Response.End();

该方案运行良好,但下载的响应速度有点慢,在生成的时候,下载的线程需要等生成的线程结束后才能运行。这样对用户的来说不太好,虽然word的生成也只是几秒钟,而且是异步生成文件,页面上有个转圈圈的图片给用户看。

方案三

生成Word的代码:

protected int CreateWord()

{

if (brCreaterAddressLock.ParticipantCount == 0)

{

lock (brCreaterAddressLock)

{

System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(() =>

{

brCreaterAddressLock.AddParticipant();

ProjectWord word = new ProjectWord();

int i = 0;

while (i <= 10)

{

try

{

word.Save(@"D:\NewWord.docx");

}

catch

{

}

finally

{

brCreaterAddressLock.RemoveParticipant();

isCreatingAddress = false;

}

}

}));

t.Start();

}

}

 

System.IO.FileInfo file = new System.IO.FileInfo(strFilePath);

 

return file.Length;

 

 

}

public static System.Threading.Barrier brCreaterAddressLock = new System.Threading.Barrier(0);

下载Word的代码:

Handler.brCreaterAddressLock.AddParticipant();

Handler.brCreaterAddressLock.SignalAndWait();

Handler.brCreaterAddressLock.RemoveParticipant();//要注意这句,SignalAndWait()不会帮你移除一个参与者,如果没这句的话,在生成的时候 if (brCreaterAddressLock.ParticipantCount == 0)这句就只会运行一次

Response.ContentType = "application/x-zip-compressed";

Response.AddHeader("Content-Disposition", "attachment;filename=" + Path.GetFileName(strFilePath));

Response.TransmitFile(strFilePath);

Response.Flush();

Response.End();

这样的话,用户在文件生成中的时候就会给他直接旧版文件的大小,加快了异步的响应速度,提高了用户体验。


<script type="text/javascript"><!--google_ad_client = "ca-pub-1944176156128447";/* cnblogs 首页横幅 */google_ad_slot = "5419468456";google_ad_width = 728;google_ad_height = 90;//--></script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
原创粉丝点击