CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  .NET技术 >  C#

c#多线程写文件

楼主babyphenix()2006-10-12 17:31:53 在 .NET技术 / C# 提问

现在有个多线程下载的类,好多线程同时写一个文件,如何实现阿,我现在是这样写的,可是结果不对,文件本来只有3M,可是写完后有6M之多,而且每次大小不同。  
  主类中是这样:  
    FileStream   fs   =   new   FileStream(filename,   System.IO.FileMode.Create);  
   
  各个线程类中这样用     fs.Seek(startPosition,   SeekOrigin.Begin);然后写stream.  
  主要的思想是要每个线程写文件中的固定的块,所以这个地方有个偏移量定义。  
   
  最后各个线程都写完后主类关闭fs.  
   
  各位给出个主意啊 问题点数:100、回复次数:26Top

1 楼fd7893(看着办吧)回复于 2006-10-12 17:38:56 得分 0

这样可不太好办啊!可行的方法:  
   
  每个线程都开一个临时文件   写   ,全部写完后合并这些文件。Top

2 楼diandian82(点点(nothing))回复于 2006-10-12 17:43:49 得分 0

这个有意思,不知道能否实现,看看先。Top

3 楼wwqna(york)回复于 2006-10-12 18:01:41 得分 20

private   bool   Writing   =   false;  
  private   string   filename   =   @"c:\1.dat";  
  byte   index   =   0;  
   
   
  private   void   Form1_Load(object   sender,   System.EventArgs   e)  
  {  
  for(byte   i   =   0;   i   <   3;   i++)  
  {  
  ThreadStart   strat   =   new   ThreadStart(WriteFile);  
  Thread   thread   =   new   Thread(strat);  
  thread.Start();  
  }  
   
   
  }  
   
  private   void   WriteFile()  
  {  
  index++;  
  byte   num   =   index;  
   
  byte[]   bytes   =   new   byte[1024];  
  for(int   i   =   0;   i   <   1024;   i++)  
  {  
  bytes[i]   =   num;  
  }  
   
  while(Writing   ==   true)  
  {  
  Application.DoEvents();  
  }  
   
  Writing   =   true;  
  FileStream   fs   =   new   FileStream(filename,   FileMode.OpenOrCreate,   FileAccess.Write);  
  fs.Seek((num   -1)   *   1024,   0);  
  fs.Write(bytes,   0,   bytes.Length);  
  fs.Close();  
  Writing   =   false;  
   
  Debug.WriteLine(num   +   "end");  
   
  }  
   
   
   
  我调试了的,绝对没有问题Top

4 楼wwqna(york)回复于 2006-10-12 18:02:17 得分 0

保证文件大小为3K,你可以用UE打开看一下Top

5 楼sgear(没有不结贴记录)回复于 2006-10-12 19:32:09 得分 0

帮顶。。。Top

6 楼Knight94(愚翁)回复于 2006-10-12 21:03:14 得分 0

参看  
  http://blog.csdn.net/Knight94/archive/2006/10/12/1332160.aspxTop

7 楼whq1982()回复于 2006-10-12 23:16:47 得分 0

多线程得注意互斥啊Top

8 楼free_wang()回复于 2006-10-13 01:06:17 得分 0

顶Top

9 楼zlkingdom(风之悲伤)回复于 2006-10-13 10:00:08 得分 0

你用了几个线程写文件啊?Top

10 楼babyphenix()回复于 2006-10-13 10:07:20 得分 0

使用了   Application.DoEvents();   下载正常了。还有个问题,如果这样的话,现在是不是真正的多线程,会不会因为写文件操作在排队从而还是想当与但线程操作?Top

11 楼wwqna(york)回复于 2006-10-13 10:59:54 得分 0

是不是多线程,看看就知道了  
   
  不明白你第二句什么意思Top

12 楼babyphenix()回复于 2006-10-13 11:49:17 得分 0

这个写法在winform中是可以工作的,但是我要拿到asp中使用就不行了,没有DoEvent()这个方法阿?Top

13 楼wwqna(york)回复于 2006-10-13 11:54:38 得分 0

直接删掉也可以的呀Top

14 楼wwqna(york)回复于 2006-10-13 11:55:02 得分 0

或是随便写个语句也可以的Top

15 楼bomb_boy(梦之星)回复于 2006-10-13 12:07:42 得分 0

wwqna(york)   的方法不安全,写的大了,肯定不行,因为太小了所以成功机会很大。Top

16 楼wwqna(york)回复于 2006-10-13 12:42:01 得分 0

楼上的,怎么不安全了,为什么?  
   
  你有没有安全点的?Top

17 楼aafshzj(生活需要breakthrough)回复于 2006-10-13 12:44:04 得分 50

wwqna(york)的算法很详细,提供了某一种思路,应该会对楼主有所启发。  
   
  不过,这个算法并不很严格。在多线程长期测试下一定还会出现问题,原因就在这段代码:  
  while(Writing   ==   true)  
  {  
  ......  
  }  
   
  Writing   =   true;  
  ......  
  Writing   =   false;  
  这里存在潜在问题:如果A线程执行“Writing   =   false;”后,几乎同时有B、C两个线程执行"while(Writing   ==   true)"并在任何一方执行到"Writing   =   true;"语句之前均完成了实质性判断的语句(无论时间片如何来回分配),那么二者就又将可以同时执行写I/O的代码。  
   
  其实考虑到如下两点:  
  1)文件读写,就其本质讲都无可避免是准单线程的,这是由硬盘的工作原理决定的  
  2)文件下载的速度瓶颈主要在于下载而不在于写硬盘。  
   
  我建议楼主考虑如下做法:  
  1)多线程下载,下载结果放入一个缓存池,并对每个结果标注其在文件中的具体位置。  
  2)单线程写文件,该线程根据缓存池的各下载结果写文件,并将写过的下载结果从缓存池中清除。  
  3)把某段下载结果写入缓存池或删除的缓存池本身应作互斥,但是这种操作非常短暂,互斥几乎不会影响什么性能  
  4)写文件的线程在找不到内容而又确定还未下载完毕时,可以通过等待固定时间或者下载线程触发的形式交出CPU使用权,并在恰当的时机继续工作。  
   
   
   
  欢迎大家来我的博客作客:http://blog.csdn.net/aafshzj/  
  我正在写一系列关于AAF组件框架的文章。该框架能对开发工作提供很多帮助,并极大地提高开发效率。希望大家看一看并提出宝贵建议。  
  Top

18 楼babyphenix()回复于 2006-10-13 13:11:39 得分 0

谢谢各位的见解:  
  其实主要是这点:文件下载的速度瓶颈主要在于下载而不在于写硬盘。如果大多数情况是这样的话,就不考虑多线程写同一个文件了。现在我的稳定版本是写多个临时文件然后合并文件,原来的考虑是如果文件操作时间的数量级和下载时间的数量级相当的话,就要考虑尽量减少对文件的操作过程,所以有了这个问题。这样看来我的考虑是多余的了。  
   
  再次谢谢各位的热情回答。Top

19 楼ycqing()回复于 2006-10-13 13:17:40 得分 0

UPTop

20 楼Knight94(愚翁)回复于 2006-10-13 13:39:30 得分 0

to   wwqna(york)  
   
  你的算法不是多线程同时写,因此相当于单线程写而已。  
   
  其实,由于文件分块写的位置不同,因此是可以多线程同时对一个文件进行写操作,彼此并不会产生冲突。  
   
  那么参看我写得两篇文章  
   
  借助WebService实现多线程上传文件  
  http://blog.csdn.net/Knight94/archive/2006/10/12/1332160.aspx  
   
  多线程断点续传研究  
  http://blog.csdn.net/knight94/archive/2006/08/11/1049393.aspx  
   
  其中都涉及到文件多线程写入操作,只要提供文件共享模式即可。  
  Top

21 楼jingtao_zhou(小熊)回复于 2006-10-13 13:40:54 得分 0

to:babyphenix()    
  你所谓的文件合并是怎么合并啊?  
  如果一个文件就2、3G,合并临时文件会不会很麻烦啊?Top

22 楼jingtao_zhou(小熊)回复于 2006-10-13 13:46:25 得分 0

to:Knight94(愚翁)    
  看过你写的bolg,能实现多线程断点续传。  
  ===================================  
  建议楼主也看看,至少我稍微改动一下就能用了。  
   
  Knight94(愚翁),怎么能保存文件块的信息啊?另写文件保存?  
  我想把信息放在下载的文件里,不知可否?Top

23 楼Knight94(愚翁)回复于 2006-10-13 15:06:16 得分 30

to   怎么能保存文件块的信息啊?另写文件保存?  
  我想把信息放在下载的文件里,不知可否?  
   
  要单独用一个文件来进行保存,我在多线程下载这篇文章提到这个方法,因为这个例子可以实现断点续传的,所以通过文件保存了文件分块下载信息,你可以参看一下。Top

24 楼aafshzj(生活需要breakthrough)回复于 2006-10-13 17:41:14 得分 0

多线程写文件在算法上是可以实现的,但是实际上没什么太大意义,除非你的机器上有很多其它应用也在访问硬盘,那你大概可以通过多线程以及设置线程的优先级多抢一点时间片过来。  
   
  写文件的准单线程特点我在第一个回复里已经说了:  
  “1)文件读写,就其本质讲都无可避免是准单线程的,这是由硬盘的工作原理决定的”。  
  实现理论上的多线程写文件并没有什么太大意义,甚至有些时候还会因为过多的线程导致处理器时间分片切换过于频繁而降低性能。因此,只要协调好负责下载或者接收上传的多线程以及写文件的单线程就可以了。Top

25 楼lingbo_wx(上海小浪人)回复于 2006-10-16 10:00:06 得分 0

dingTop

26 楼babyphenix()回复于 2006-10-16 10:30:34 得分 0

再次谢谢各位的讨论:  
  最后还是采用多线程写同一个文件的方式来做(其实这个也只能是相对的,绝对的多线程写单个文件是无法实现的)  
  最后发现只要在每个线程类中这样打开文件流就能实现:  
  new   FileStream(filename,     System.IO.FileMode.OpenOrCreate,     System.IO.FileAccess.ReadWrite,   System.IO.FileShare.ReadWrite);  
  另外测试中发现,多线程写同一个文件比写多个文件再合并快不了多少,再次说明了整个操作的瓶颈在下载的过程,其实只要实现多线程下载,文件操作可以两种方式都可以了。Top

相关问题

关键词

得分解答快速导航

  • 帖主:babyphenix
  • wwqna
  • aafshzj
  • Knight94

相关链接

  • CSDN .NET频道
  • .NET类图书
  • C#类图书
  • .NET类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo