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




