多线程拷贝文件 我想了很久!!!!! ( 积分: 30 )

  • 主题发起人 主题发起人 awsoft
  • 开始时间 开始时间
A

awsoft

Unregistered / Unconfirmed
GUEST, unregistred user!
高手请看 看后发表意见!!!!!!!!!
你能实现 给我点起事我实验一下! 我想了很久
我在学习多线程 ! 拿多线程拷贝来说 我用TFileStream或TMemoryStream来工作!
结果 我发现和系统的拷贝时间 差不多 !
我想 1、可能是硬盘独占 文件的读取是独占的 就是你用多线程和不用是一样的
按理说 把文件分成几个部分由多个线程同时(CPU分时间片)拷贝 应该快 !但是你想 文件的指针你能随便动吗 ? 即 第一个线程拷贝时 先动文件指针到要考的位置 然后拷贝,第二个线程拷贝时,要把文件指针改到要拷贝的地方 同里3、4、5等等线程拷贝时都要先改指针,要不然会发生错误!
问题在这里 改动指针时 别的线程是不能改的 所以我们用 信号量、互斥对象等等 控制,你想想 当一个线程拷贝时 其他线程停止等待这个线程拷完然后改指针再进行拷贝!这跟系统的拷贝没区别,还是没发挥多线程的威力! 并没多占时间片来进行拷贝,占了时间片也是等带 等待 等到别的线程拷完在改指针!
我想在计算机中 指针存在 指针寄存器里 我们用多线程时 总是一个指针寄存器在为我们工作,我们的线程不得不等着 轮流使用 ! 我想这是主要问题所在 !
如果我们把文件加载到内存里,然后分块 我们开始 多个线程从 不同内存地址开始拷贝 这我们成功了! 但 你想 就一个指针寄存器记录当前的指针位置 我们没办法 每个线程拷贝时都要用指针寄存器指向不同的位置来进行拷贝,这个过程进行中别的线程不能打扰!这样还是不行呀!!!!! 到头来还是一个线程 结果跟系统拷贝时间差不多 !由于你的代码问题(其实耽误的时间)肯定比系统拷贝要慢!
 
高手请看 看后发表意见!!!!!!!!!
你能实现 给我点起事我实验一下! 我想了很久
我在学习多线程 ! 拿多线程拷贝来说 我用TFileStream或TMemoryStream来工作!
结果 我发现和系统的拷贝时间 差不多 !
我想 1、可能是硬盘独占 文件的读取是独占的 就是你用多线程和不用是一样的
按理说 把文件分成几个部分由多个线程同时(CPU分时间片)拷贝 应该快 !但是你想 文件的指针你能随便动吗 ? 即 第一个线程拷贝时 先动文件指针到要考的位置 然后拷贝,第二个线程拷贝时,要把文件指针改到要拷贝的地方 同里3、4、5等等线程拷贝时都要先改指针,要不然会发生错误!
问题在这里 改动指针时 别的线程是不能改的 所以我们用 信号量、互斥对象等等 控制,你想想 当一个线程拷贝时 其他线程停止等待这个线程拷完然后改指针再进行拷贝!这跟系统的拷贝没区别,还是没发挥多线程的威力! 并没多占时间片来进行拷贝,占了时间片也是等带 等待 等到别的线程拷完在改指针!
我想在计算机中 指针存在 指针寄存器里 我们用多线程时 总是一个指针寄存器在为我们工作,我们的线程不得不等着 轮流使用 ! 我想这是主要问题所在 !
如果我们把文件加载到内存里,然后分块 我们开始 多个线程从 不同内存地址开始拷贝 这我们成功了! 但 你想 就一个指针寄存器记录当前的指针位置 我们没办法 每个线程拷贝时都要用指针寄存器指向不同的位置来进行拷贝,这个过程进行中别的线程不能打扰!这样还是不行呀!!!!! 到头来还是一个线程 结果跟系统拷贝时间差不多 !由于你的代码问题(其实耽误的时间)肯定比系统拷贝要慢!
 
文件拷贝速度的瓶颈主要是在IO,而不是在CPU(多线程),再多的线程效果也不会明显,更况且文件指针移来移去,很伤硬盘的。
用一个线程负责copy,用其他线程同步做其他的事情,这样比较好些
 
每个线程只读打开一个文件,各自操作
我想应该是这样做
 
我认为,多线程拷贝的应用情况应该是:从若干个相对低速设备读取数据,写入到若干个相对高速的设备,即总读取数据速率<=写入速率。当一个设备的读取速率>=另一个设备的写入速率时,多线程就没用武之地了。
补充:这里所说的设备是指顺序读写而非并发读写设备。
 
采用内存映射,多个线程各自负责文件的一部分,应该可以提高速度的。
“当一个线程拷贝时 其他线程停止等待这个线程拷完然后改指针再进行拷贝!”这样当然不会提高速度。
 
大家好 看了大家的看法 我很高兴 !
我用 Createfile API 函数 共想打开文件 ! 然后用多个线成拷贝,实现了多线成拷贝程序! 我先前说的“当一个线程拷贝时 其他线程停止等待这个线程拷完然后改指针再进行拷贝!” 利用共乡文件 每个线成可以同时拷贝文件! 但是 我发现速度并没有提高!
我想 FlashGet Netants 等都是从网络上拷贝文件! 这样能体现出多线成的好处! 我想painboy 说的有些道理!
但是据我所知 国际上有一家公司的软件就是多线成拷贝,他们是在 单机上实现的!软件名称我记不太清了 但是肯定有! 不知道他们是怎样实现的!!!!!!
高手看后请发表意见 !!!!!
 
分块来读写 1个线程管一块
 
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
OpenDialog1: TOpenDialog;
SaveDialog1: TSaveDialog;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
FromF, ToF: file;
Buf: array[1..8192] of Char;
Buf2: array[1..8192] of Char;
BufStat1,BufStat2:boolean;
//true缓存可用
hthread,hthread2:thandle;ThreadID,threadid2:DWord;
f1,f2:string;
NumRead, NumWritten, NumRead2, NumWritten2,i,j: Integer;
filesizea:longint;
bytes,myshare:word;blocks:longint;
implementation
{$R *.DFM}

function readfile(P:pointer):Longint;stdcall;
begin
//for i:=1 to length(buf)do
temp:=buf;
// try
// if (NumRead <>0) then
begin
AssignFile(FromF, f1);
Reset(FromF, 1);
//filesizea:=filesize(fromf);
// showmessage(inttostr(filesizea));

repeat
if bufstat1 then
begin
BlockRead(FromF, Buf, SizeOf(Buf), NumRead);
bufstat1:=false;
// inc(i);
end else

if bufstat2 then
begin
BlockRead(FromF, Buf2, SizeOf(Buf2), NumRead2);
bufstat2:=false;
// inc(i);

end;

until (eof(fromf));//(numread=0)and (numread2=0);
// except
// end;
CloseFile(FromF);
Result:=-1;
end;

function writefile(P:pointer):Longint;stdcall;
begin
//if (Numwrite <>numread) then
begin
// try
AssignFile(ToF, f2);
Rewrite(ToF, 1);
repeat
if not bufstat1 then
begin
BlockWrite(ToF, Buf, NumRead, NumWritten);
bufstat1:=true;
// inc(j);
end else
if not bufstat2 then
begin
BlockWrite(ToF, Buf2, NumRead2, NumWritten2);
bufstat2:=true;
// inc(j);
end;

until (NumWritten =0)and (NumWritten2=0);// (filesizea<>filesize(tof));
//this simples not correctly
//read 82,write 80
// end;
// except
// end;

CloseFile(ToF);
Result:=-1;
end;
procedure TForm1.Button1Click(Sender: TObject);
//var
// i:integer;
begin
if OpenDialog1.Execute then
{ Display Open dialog box }
begin
if SaveDialog1.Execute then
{ Display Save dialog box}
begin
// Canvas.TextOut(10, 10, 'Copying ' + IntToStr(FileSize(FromF))
// + ' bytes...');
//repeat
f1:=opendialog1.FileName;
f2:=savedialog1.FileName;
bufstat1:=true;
bufstat2:=true;
// for i:=1 to length(buf)do
buf:='0';
// for i:=1 to length(buf2)do
buf2:='0';
hThread:=CreateThread(nil,0,@readFile,nil,0,ThreadID);
if hThread=0 then
readFile(nil);
{ not use thread }
hThread2:=CreateThread(nil,0,@writeFile,nil,0,ThreadID2);
if hThread2=0 then
writeFile(nil);
{ not use thread }
// until (NumRead = 0) or (NumWritten <> NumRead);
// showmessage('ok');
// showmessage('写入'+inttostr(j));
// showmessage('读取'+inttostr(i));
end;
// showmessage('ok');
end;
end;

这个东东,问题在哪里,拷贝后的文件不正确哦!
读,写线程来处理,利用缓存可以提速,,,,,,
至于分块则不见得
 
多线程拷贝文件,要用内存影像文件。每个线程负责一个指针的读写。我写过一个,基本上和windows自带的拷贝功能效率相差无几。5、600M的文件基本上慢了1、2秒的样子。超过windows是不可能的啊:)
 
拷贝文件也用多线程?没必要吧?
我试过,即便是scsi硬盘,拷文件速度也不怎么样,现在计算机硬件体系的整体瓶颈在磁盘上面,线程再多也快不到哪里去
 
我记得Another_eYes大虾在回答类似&quot;多线程拷贝文件&quot;问题的帖子中,有一句经典的话来形容这种操作是:&quot;脱裤子放屁,多此一举&quot;!IO层永远是阻塞的,无论你用多少个线程写入文件都不能提高速度.
 
这个贴子已经不用在讨论了,答案已经很明显
&quot;脱裤子放屁,多此一举&quot;! 形容很贴切.
 
好,帮顶


--------签名档---------------------------

比肩国内顶尖源码下载站点 -> 源码我爱你

http://www.source520.com
http://www.source520.net
80G源码电子书免费免注册下载,大量精辟技术文档库随时更新
******************************************************************
附:为了站点持续发展,现有本站近年来收藏的大量大型商业源码低价出售,
详情请进入以下链接查看:
http://www.source520.com/building_delphi.htm

浏览商业代码请从如下URL进入查看实物:
1.商业源码库1: ftp://source520see3:browse@61.152.199.245/
2.商业源码库2: ftp://source520see2:browse@61.152.199.245/
 
后退
顶部