我一直想知道,怎样挖掘系统的文件拷贝潜能,是否如果能避开系统的管理而实现快速拷贝文件。请各位大侠踊跃探讨!

解决方案 »

  1.   

    不用copyfile,外部命令,你像用流,流进流出不成?
      

  2.   

    我的意思是不用ASSIGNFILE、FILESTREAM等的普通方法
      

  3.   

    微软使用的拷贝系统由于运行权限、系统结构等方面的限制不可能是最优的方案,我曾经看过一个拷贝文件的例子,是系统的10倍以上,是老外的DEMO,老外能实现,我们就不能,不甘心!请继续讨论,只要说的好,我一定给分,不过不要再谈系统的已有拷贝函数,或只是简单的用流,我做的使用流靠别文件的速度都是COPYFILE的1.7倍,所以就不要谈了!
      

  4.   

    GetMem(buf, 65000);
      Repeat
        BlockRead(f1, buf^, 65000, xfer);
        BlockWrite(f2, buf^, xfer);
      Until xfer < 65000;
      

  5.   

    大哥我使的就是类似的方法GetMem(buf, 65000);
      Repeat
        {BlockRead(f1, buf^, 65000, xfer);
        BlockWrite(f2, buf^, xfer);}

        FileStream:=TFileStream.Create('c:\a.dat',fmcreate);
        fileStream.copyfrom(DescFileStream,DescFileStream.Size);

        FileStream:=TFileStream.Create('c:\a.dat',fmcreate);
        fileStream.copyfrom(DescFileStream,copysize);
        COPYSIZE是分包拷贝的方法,可以拷贝大文件。
      Until xfer < 65000;
    但我说的是不使用这样的方法。
    这是常规方法
      

  6.   

    而且上述方法并不是缓冲区越大越快,比较理想的是与当前文件系统的镞大小相同或其整数倍
    如WIDNOWS下为4K,不知大家是否测试过LINUX下的文件拷贝,他的速度与内存的大小成正比,即内存越大速度越快。WINDOW下就不是,我的测试是在同一台机器,所以WINDOW自身的文件拷贝不可能快,需要另开思路。
      

  7.   

    可以在多线程的方式下执行,以overlapped的形式打开目的文件,然后每个线程读取和写入该文件中的不同位置。
      

  8.   

    怎样overlapped的形式打开目的文件
      

  9.   

    BOOL ReadFileEx(    HANDLE hFile, // handle of file to read 
        LPVOID lpBuffer, // address of buffer 
        DWORD nNumberOfBytesToRead, // number of bytes to read 
        LPOVERLAPPED lpOverlapped, // address of offset 
        LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine  // address of completion routine 
       );在帮助里查到,好象是说这个函数是以overlapped的形式打开目的文件
      

  10.   

    overlapped结构中的一个成员是偏移量,利用它即可
      

  11.   

    好,我正在做,大家继续讨论,我做好DEMO会贴上来
      

  12.   

    关注中,喜欢这样的帖子
    如果是linux文件的系统的话,可以自己写文件操作的系统调用,重新编译内核
    windows只能利用现成的api构造算法,显然能力有限,最好能重写api
      

  13.   

    一点构想:
    提升权限到ring0,在内存中划分一快足够大的空间,最好是比文件大
    直接读取磁盘到内存
    再从写入磁盘
    这样读写次数比较少,应该会比较快吧有说错不要丢番茄啊~
      

  14.   

    用winexec调用dos命令xxcopy
    要装xxcopy
      

  15.   

    兄弟们,发布第一稿,由于语句多,分四次贴出来。拷贝速度是正常的1.5倍即50/125 
    unit PartCopyThread_NoEx;interfaceuses
      Classes, Windows, Types, SysUtils, Math, Controls, mmSystem, Forms, IdGlobal, SyncForm, Dialogs
      , RTLConsts, Syncobjs;
    type
      TCompletedRoutine=procedure (dwErr: DWORD; cbWritten: DWORD; pOVL: POVERLAPPED); stdcall;
      TPartCopyThread=class;
      PInfo = ^TInfo;
      TInfo = packed record
        Overlap: OVERLAPPED;
        CopySize:DWORD;
        FileSourceObj,FileDescObj: THandle;
        Thread:TPartCopyThread;
        IsWrite:Boolean;
        FileName:Array[0..1024] of Char;
        chBuf: PByte;
      end;  TFileStreamEx=Class(THandleStream)
      private
        function FileCreatev(const FileName: string): Integer;
        function FileOpenv(const FileName: string; Mode: LongWord): Integer;
        function FileReadv(Handle: Integer; var Buffer; Count: LongWord; ReadInfo:OVERLAPPED; ProcObj:Pointer): Integer;
        function FileWritev(Handle: Integer; const Buffer; Count: LongWord; WriteInfo:OVERLAPPED; ProcObj:Pointer): Integer;
      public
        Constructor Create(FileName:String; CreateMode:DWORD);
      end;  TPartCopyThread = class(TThread)
      private
        Qu,ShowMessageResult:TModalResult;
        List:TStrings;
        Error:String;
        InfoList:TList;
        Param:Array of String;
        ShowType:TShowType;
        SourceName,DescName,OutPath,Caption,CurStr,OldStr,ErrorName:String;
        CopyForm:TForm;
        CopySize:Integer;
        TmpSize:Integer;
        DescCurPos:Integer;
        ProcObj:TCompletedRoutine;
        CopyCount,DecCount:Integer;
        Event:Array of TSimpleEvent;
        HdArray:Array of THandle;
        procedure ShowSize;
        procedure DoWriteList;
        procedure DoFinally;
        procedure ShowMesssageEx;
        procedure SetEvent(Enabled:Boolean);
        procedure FreeInfos;    { Private declarations }
      protected
        procedure Execute; override;
        procedure OnClose(Sender:TObject);
      public
        Constructor Create(sList:TStrings; sOutPath:String; sCopyForm:TForm; sCopySize, sCopyCount:Integer);
      end;implementation
      

  16.   

    uses Main, Question, Say, Display, FileOpen, CopyFile;Var
        ReadLock,WriteLock:TCriticalSection;
        PubInfo:PInfo=nil;{ Important: Methods and properties of objects in VCL or CLX can only be used
      in a method called using Synchronize, for example,      Synchronize(UpdateCaption);  and UpdateCaption could look like,    procedure TCopyThread.UpdateCaption;
        begin
          Form1.Caption := 'Updated in a thread';
        end; }{ TCopyThread }constructor TPartCopyThread.Create(sList: TStrings; sOutPath:String; sCopyForm:TForm; sCopySize, sCopyCount:Integer);
    Var
        i:Integer;
    begin
        Inherited Create(True);
        InfoList:=TList.Create;
        CopyCount:=sCopyCount;
        CopyForm:=TDForm(sCopyForm);
        List:=TStringList.Create;
        List.Text:=sList.Text;
        OutPath:=sOutPath;
        FreeOnTerminate:=True;
        CopySize:=sCopySize;
        OnTerminate:=OnClose;
        Qu:=mrNone;
        SetLength(Event,CopyCount);
        SetLength(HdArray,CopyCount);
        For i:=Low(Event) to High(Event) do
        begin
            Event[i]:=TSimpleEvent.Create;
            HdArray[i]:=Event[i].Handle;
        end;
        Resume;
    end;procedure TPartCopyThread.DoFinally;
    begin
        TDForm(CopyForm).Panel2.Caption:=Caption;
        TDForm(CopyForm).PageControl1.ActivePageIndex:=2;
    end;procedure TPartCopyThread.DoWriteList;
    begin
        TDForm(CopyForm).ListBox2.Items.Add(ErrorName);
    end;procedure TPartCopyThread.Execute;
    Var
        SourceBytes,i,j,Count,TimeStart,sCopySize,sCopyCount:Integer;
        sCount:Cardinal;
        Str,dStr:String;
        pTime:Integer;
        FileAttrib1,FileAttrib2:WIN32_FILE_ATTRIBUTE_DATA;
        OldErrMode:UINT;
        SourceHd,DescHd:THandle;
        Head:THeaderInfo;
        Info:PInfo;
        Sizees:DWORD;
    begin
        OldErrMode:=SetErrorMode(SEM_FailCriticalErrors);
        TimeStart:=GetTickCount;
        Try
            PostMessage(CopyForm.Handle,WM_SETMAXPROG1,List.Count,0);
            For i:=0 to List.Count-1 do
            begin
                DecCount:=CopyCount;
                if TDForm(CopyForm).Check or Terminated then
                    Break;
                Try
                    Try
                        SourceName:=List.Strings[i];
                        if TDForm(CopyForm).RadioButton2.Checked then
                        begin
                            Str:=UpperCase(Trim(List.Strings[i]));
                            dStr:=UpperCase(ExtractFileDrive(Str));
                            Str:=Copy(Str,Length(dStr)+2,Length(Str));
                            DescName:=OutPath+Str;
                            Str:=ExtractFileDir(DescName);
                            if DirectoryExists(Str)=False then
                                if ForceDirectories(Str)=False then
                                    Continue;
                        end
                        else
                            DescName:=OutPath+ExtractFileName(List.Strings[i]);
      

  17.   

    if FileExists(DescName) then
                        begin
                            SetLength(Param,2);
                            Param[0]:='文件已经存在,是否覆盖?';
                            Param[1]:=DescName;
                            ShowType:=stSimpleQuestion;
                            Synchronize(ShowMesssageEx);
                            if ShowMessageResult<>idyes then
                                Continue;
                        end;
                        SourceHd:=CreateFile(PChar(SourceName), GENERIC_READ,
                            FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
                        if SourceHd=0 then
                        begin
                            SetLength(Param,2);
                            Param[0]:='文件打开失败,是否继续';
                            Param[1]:=SourceName;
                            ShowType:=stSimpleQuestion;
                            Synchronize(ShowMesssageEx);
                            if ShowMessageResult=idyes then
                                Continue
                            else
                                Break;
                        end;
                        if FileExists(DescName) then
                            DeleteFile(DescName);
                        DescHd:=CreateFile(PChar(DescName), GENERIC_WRITE,
                            FILE_SHARE_WRITE, nil, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, 0);
                        if DescHd=0 then
                        begin
                            SetLength(Param,2);
                            Param[0]:='文件打开失败,是否继续';
                            Param[1]:=DescName;
                            ShowType:=stSimpleQuestion;
                            Synchronize(ShowMesssageEx);
                            if ShowMessageResult=idyes then
                            begin
                                CloseHandle(SourceHd);
                                Continue
                            end
                            else
                                Break;
                        end;
                        Count:=GetFileSize(SourceHd,nil);
                        if Count<=0 then
                        begin
                            CloseHandle(SourceHd);
                            SourceHd:=0;
                            CloseHandle(DescHd);
                            DescHd:=0;
                            Continue;
                        end;
                        SourceBytes:=Count div CopyCount;
                        if SourceBytes=0 then
                            sCopyCount:=1
                        else
                            sCopyCount:=CopyCount;
                        sCopySize:=Count mod CopyCount;
                        PostMessage(CopyForm.Handle,WM_SETMAXPROG2,CopyCount,0);
                        SetEvent(false);
                        FreeInfos;
      

  18.   

    uses shellapi
    function copyTheFile(filename:string;Recycle:boolean):Integer;
    Var SHFileOpStruct:TSHFileOpStruct;
    begin
     Filename:=filename+#0#0;
     With SHFileOpStruct do
     begin
       Wnd := Application.Handle;
       wFunc := FO_copy;
       pFrom := pchar(Filename);
       pTo:= nil;
       fFlags := FOF_FILESONLY + FOF_NOCONFIRMATION + FOF_SILENT + FOF_NOERRORUI;
       if Recycle then fFlags:=fFlags + FOF_ALLOWUNDO
     end;
     Result:=SHFileOperation(SHFileOpStruct);
    End;
      

  19.   

    呵呵,这个话题好,继续继续,我一般都用流多或者系统自带的函数。自己写的话很容易考虑不全,比如说文件的属性、在NTFS下要是已被加密怎样处理。
      

  20.   

    to  APPFIRST(一研) :你的代码好像少了一贴。
      

  21.   

    unit PartCopyThread;
    interface
    uses
      Classes, Windows, Types, SysUtils, Math, Controls, mmSystem, Forms, IdGlobal, SyncForm, Dialogs
      , RTLConsts, Syncobjs;
    type
      TCompletedRoutine=procedure (dwErr: DWORD; cbWritten: DWORD; pOVL: POVERLAPPED); stdcall;
      TPartCopyThread=class;
      PInfo = ^TInfo;
      TInfo = packed record
        Overlap: OVERLAPPED;
        CopySize:DWORD;
        FileSourceObj,FileDescObj: THandle;
        Thread:TPartCopyThread;
        IsWrite:Boolean;
        FileName:Array[0..1024] of Char;
        chBuf: PByte;
        Int:PInteger;
        Count,Start:Integer;
        Main:TForm;
      end;  TPartCopyThread = class(TThread)
      private
        Qu,ShowMessageResult:TModalResult;
        List:TStrings;
        Error, Caption:String;
        Param:Array of String;
        ShowType:TShowType;
        SourceName,DescName,OutPath,ErrorName:String;
        CopyForm:TForm;
        CopySize:Integer;
        procedure DoWriteList;
        procedure ShowMesssageEx;
        procedure DoFinally;    { Private declarations }
      protected
        procedure Execute; override;
        procedure OnClose(Sender:TObject);
      public
        CopyCount:Integer;
        DecCount:Integer;
        Events:TSimpleEvent;
        Constructor Create(sList:TStrings; sOutPath:String; sCopyForm:TForm; sCopySize, sCopyCount:Integer);
      end;implementationuses Main, Question, Say, Display, FileOpen, CopyFile, PartCopyThread_Ex;
    Var
        PubInfo:PInfo=nil;
    constructor TPartCopyThread.Create(sList: TStrings; sOutPath:String; sCopyForm:TForm; sCopySize, sCopyCount:Integer);
    Var
        i:Integer;
    begin
        Inherited Create(True);
        Events:=TSimpleEvent.Create;
        CopyCount:=sCopyCount;
        CopyForm:=TDForm(sCopyForm);
        List:=TStringList.Create;
        List.Text:=sList.Text;
        OutPath:=sOutPath;
        FreeOnTerminate:=True;
        CopySize:=sCopySize;
        OnTerminate:=OnClose;
        Qu:=mrNone;
        Resume;
    end;procedure TPartCopyThread.DoWriteList;
    begin
        TDForm(CopyForm).ListBox2.Items.Add(ErrorName);
    end;procedure TPartCopyThread.Execute;
    Var
        SourceBytes,i,j,k,Count,TimeStart,sCopySize,sCopyCount:Integer;
        sCount:Cardinal;
        Str,dStr:String;
        pTime:Integer;
        FileAttrib1,FileAttrib2:WIN32_FILE_ATTRIBUTE_DATA;
        OldErrMode:UINT;
        SourceHd,DescHd:THandle;
        Head:THeaderInfo;
        Info:PInfo;
        Sizees:DWORD;
        oConnect:OVERLAPPED;
        Tmp:Array[0..1] of Byte;
        PInt:PInteger;
        TmpCount:Integer;
    begin
        OldErrMode:=SetErrorMode(SEM_FailCriticalErrors);
        TimeStart:=GetTickCount;
        TmpCount:=20*1024*1024;
        Try
            PostMessage(CopyForm.Handle,WM_SETMAXPROG1,List.Count,0);
            For i:=0 to List.Count-1 do
            begin
                if TDForm(CopyForm).Check or Terminated then
                    Break;
                Try
                    Try
                        SourceName:=List.Strings[i];
                        if TDForm(CopyForm).RadioButton2.Checked then
                        begin
                            Str:=UpperCase(Trim(List.Strings[i]));
                            dStr:=UpperCase(ExtractFileDrive(Str));
                            Str:=Copy(Str,Length(dStr)+2,Length(Str));
                            DescName:=OutPath+Str;
                            Str:=ExtractFileDir(DescName);
                            if DirectoryExists(Str)=False then
                                if ForceDirectories(Str)=False then
                                    Continue;
                        end
                        else
                            DescName:=OutPath+ExtractFileName(List.Strings[i]);
                        if FileExists(DescName) then
                        begin
                            SetLength(Param,2);
                            Param[0]:='文件已经存在,是否覆盖?';
                            Param[1]:=DescName;
                            ShowType:=stSimpleQuestion;
                            Synchronize(ShowMesssageEx);
                            if ShowMessageResult<>idyes then
                                Continue;
                        end;
                        SourceHd:=CreateFile(PChar(SourceName), GENERIC_READ,
                            FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
                        if SourceHd=0 then
                        begin
                            SetLength(Param,2);
                            Param[0]:='文件打开失败,是否继续';
                            Param[1]:=SourceName;
                            ShowType:=stSimpleQuestion;
                            Synchronize(ShowMesssageEx);
                            if ShowMessageResult=idyes then
                                Continue
                            else
                                Break;
                        end;
                        if FileExists(DescName) then
                            DeleteFile(DescName);
                        DescHd:=CreateFile(PChar(DescName), GENERIC_WRITE,
                            FILE_SHARE_WRITE, nil, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, 0);
      

  22.   

    if DescHd=0 then
                        begin
                            SetLength(Param,2);
                            Param[0]:='文件打开失败,是否继续';
                            Param[1]:=DescName;
                            ShowType:=stSimpleQuestion;
                            Synchronize(ShowMesssageEx);
                            if ShowMessageResult=idyes then
                            begin
                                CloseHandle(SourceHd);
                                Continue
                            end
                            else
                                Break;
                        end;
                        Count:=GetFileSize(SourceHd,nil);
                        if Count=0 then
                        begin
                            Continue
                        end;
                        if (CopyCount=1) and (Count>TmpCount) then
                        begin
                            SourceBytes:=TmpCount;
                            sCopyCount:=Count div SourceBytes;
                            sCopySize:=Count-SourceBytes*sCopyCount;
                            DecCount:=sCopyCount;
                        end
                        else
                        begin
                            SourceBytes:=Count div CopyCount;
                            if SourceBytes=0 then
                                sCopyCount:=1
                            else
                                sCopyCount:=CopyCount;
                            sCopySize:=Count mod CopyCount;
                            if CopyCount<>1 then
                                DecCount:=SCopyCount;
                            if DecCount=1 then
                                DecCount:=1;
                            Events.ReSetEvent;
                        end;
                        PostMessage(CopyForm.Handle,WM_SETMAXPROG2,sCopyCount,0);
                        For j:=0 to sCopyCount-1 do
                        begin
                            New(PubInfo);
                            FillMemory(PubInfo,SizeOf(TInfo),0);
                            StrPCopy(PubInfo^.FileName,SourceName);
                            PubInfo^.Thread:=Self;
                            PubInfo^.Overlap.Offset:=j*SourceBytes;
                            if j=sCopyCount-1 then
                                PubInfo^.CopySize:=SourceBytes+sCopySize
                            else
                                PubInfo^.CopySize:=SourceBytes;
                            PubInfo^.chBuf:=AllocMem(PubInfo^.CopySize);
                            PubInfo^.FileSourceObj:=SourceHd;
                            PubInfo^.FileDescObj:=DescHd;
                            PubInfo^.Main:=CopyForm;
                            PubInfo^.Count:=j+1;
                            PubInfo^.Start:=CopyCount;
                            PubInfo^.Int:=PInt;                        if Not ReadFileEx(PubInfo^.FileSourceObj,PubInfo^.chBuf,
                                PubInfo^.CopySize,@(PubInfo^.Overlap),@CompletedReadRoutine) then
                            begin
                                if GetLastError=997 then
                                    Continue;
                                ShowMessage(IntToStr(GetLastError));
                                SetLength(Param,2);
                                Param[0]:='读文件块'+IntToStr(j+1)+'失败,是否继续?';
                                Param[1]:=DescName;
                                ShowType:=stSimpleQuestion;
                                Synchronize(ShowMesssageEx);
                                Dispose(PubInfo);
                                if ShowMessageResult<>idyes then
                                    break
                                else
                                    Continue;
                            end
                            else
                                SleepEx(100,true);
                        end;
                        if CopyCount<>1 then
                        begin
                            While Events.WaitFor(100)<>wrSignaled do
                            begin
                                SleepEx(100,true);
                            end;
                        end;                Except
                        On E:Exception do
                        begin
                            ErrorName:=List.Strings[i];
                            Synchronize(DoWriteList);
                            Continue;
                        end;
                    end;
                Finally
                    if SourceHD<>0 then
                    begin
                        CloseHandle(SourceHD);
                        SourceHd:=0;
                    end;
                    if DescHD<>0 then
                    begin
                        CloseHandle(DescHD);
                        DescHd:=0;
                    end;
                    if CopyCount<>1 then
                        PostMessage(CopyForm.Handle,WM_SETVALPROG1,i+1,0);
                end;
            end;
            if CopyCount=1 then
            begin
                While Events.WaitFor(100)<>wrSignaled do
                begin
                    SleepEx(100,true)
                end;
            end;
        Finally
            pTime:=GetTickCount-TimeStart;
            dStr:=FloatToStr(pTime div (1000*60));
            if TDForm(CopyForm).Check then
                Caption:='文件拷贝未完成!错误信息:'+Error
            else
                Caption:='文件拷贝完成!共花费时间:'+IntToStr(pTime div (1000*60))+'分'+FloatToStr(pTime mod (1000*60))+'毫秒';
            Synchronize(DoFinally);
            SetErrorMode(OldErrMode);
        end;
    end;procedure TPartCopyThread.DoFinally;
    begin
        TDForm(CopyForm).Panel2.Caption:=Caption;
        TDForm(CopyForm).PageControl1.ActivePageIndex:=2;
    end;procedure TPartCopyThread.OnClose(Sender: TObject);
    Var
        i:Integer;
    begin
        Events.Free;
        TDForm(CopyForm).SpeedButton4.Caption:='开始文件拷贝';
        TDForm(CopyForm).CheckBox3.Enabled:=true;
    end;procedure TPartCopyThread.ShowMesssageEx;
    begin
        ShowMessageResult:=SyncForm.ShowMessage(Param,ShowType);
    end;end.
      

  23.   

    unit Display;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, Gauges, Buttons, StdCtrls, ExtCtrls, Menus, FileCtrl, Clipbrd, ShellApi,
      ComCtrls, CopyThread, XPMenu, ImgList, Mask, Syncobjs, IdGlobal, Spin, Math;
    Const
        WM_SETMAXPROG1=WM_USER+100;
        WM_SETMAXPROG2=WM_USER+101;
        WM_SETVALPROG1=WM_USER+102;
        WM_SETVALPROG2=WM_USER+103;
        WM_SETVALPROG2_2=WM_USER+104;
        WM_TEST=WM_USER+105;
        WM_COPYEND=WM_USER+106;procedure CompletedReadRoutine(dwErr: DWORD; cbBytesRead: DWORD; pOVL: POVERLAPPED); stdcall;
    procedure CompletedWriteRoutine(dwErr: DWORD; cbBytesRead: DWORD; pOVL: POVERLAPPED); stdcall;implementationuses PartCopyThread;Var
        ReadLock,WriteLock:TCriticalSection;procedure CompletedReadRoutine(dwErr: DWORD; cbBytesRead: DWORD; pOVL: POVERLAPPED); stdcall;
    var
      Info: PartCopyThread.PInfo;
      FWrite: Boolean;
    begin
        ReadLock.Acquire;
        Try
            Info:=PartCopyThread.PInfo(pOVL);
            if ((dwErr = 0) and (cbBytesRead <> 0)) then
            begin
                if Not Info^.IsWrite then
                begin
                    pOVL^.hEvent:=Integer(Info);
                    fWrite := WriteFileEx(Info^.FileDescObj,
                      Info^.chBuf,
                      cbBytesRead,
                      pOVL^,
                      @CompletedWriteRoutine);
                end
            end
            else
            begin
                if dwErr<>0 then
                begin
                    TDForm(Info^.Main).ListBox2.Items.Add(Info^.FileName);
                end
                else if cbBytesRead=0 then
                begin
                end;
            end;
        Finally
            ReadLock.Release;
        end;
    end;procedure CompletedWriteRoutine(dwErr: DWORD; cbBytesRead: DWORD; pOVL: POVERLAPPED); stdcall;
    var
      Info: PartCopyThread.PInfo;
      FWrite: Boolean;
    begin
        WriteLock.Acquire;
        Try
            Try
                Info:=PartCopyThread.PInfo(Ptr(pOVL^.hEvent));
                if ((dwErr = 0) and (cbBytesRead <> 0)) then
                begin
                    Dec(Info^.Thread.DecCount);
                    if Info^.Thread.DecCount<=0 then
                        Info^.Thread.Events.SetEvent;
                end
                else
                begin
                    if dwErr<>0 then
                    begin
                        TDForm(Info^.Main).ListBox2.Items.Add(Info^.FileName);
                    end
                    else if cbBytesRead=0 then
                    begin
                    end;
                end;
                //PostMessage(Info^.Main.Handle,WM_SETVALPROG2_2,0,0);
                //if Info^.Thread.CopyCount=1 then
                //    PostMessage(Info^.Main.Handle,WM_SETVALPROG1,0,0);
                if Info^.Start=1 then
                    PostMessage(Info^.Main.Handle,WM_SETVALPROG1,Info^.Count,0);
                PostMessage(Info^.Main.Handle,WM_SETVALPROG2_2,0,0);
                FreeMem(Info^.chBuf);
                Info^.Int:=nil;
                Dispose(Info);
            Except
                PostMessage(0,0,0,0);
            end;
        Finally
            WriteLock.Release;
        end;
    end;procedure TDForm.WMSETMAXPROG1(var Msg: TMessage);
    begin
        Gauge2.MaxValue:=Msg.WParam;
        Gauge2.Progress:=0;
    end;procedure TDForm.WMSETMAXPROG2(var Msg: TMessage);
    begin
        Gauge1.MaxValue:=Msg.WParam;
        Gauge1.Progress:=0;
    end;procedure TDForm.WMSETVALPROG1(var Msg: TMessage);
    begin
        Gauge2.Progress:=Gauge2.Progress+1;
    end;procedure TDForm.WMSETVALPROG2(var Msg: TMessage);
    begin
        Gauge1.Progress:=Msg.WParam;
    end;procedure TDForm.WMSETVALPROG2_2(var Msg: TMessage);
    begin
        Gauge1.Progress:=Gauge1.Progress+1;
    end;procedure TDForm.WMTEST(var Msg: TMessage);
    begin
        ShowMessage('ddddddddddddd');
    end;procedure TDForm.WMCOPYEND(var Msg: TMessage);
    Var
        pTime:Integer;
        dStr:String;
        Info:PartCopyThread.PInfo;
    begin
        Info:=PartCopyThread.PInfo(Ptr(Msg.WParam));
        pTime:=GetTickCount-Info^.Int^;
        dStr:=FloatToStr(RoundTo(pTime/(1000*60),-2));
        Panel2.Caption:='文件拷贝完成!共花费时间:'+IntToStr(pTime div (1000*60))+'分'+Copy(dStr,Length(dStr)-1,2)+'秒';
        PageControl1.ActivePageIndex:=2;
        Dispose(Info^.Int);
        Dispose(Info^.chBuf);
        Dispose(Info);
    end;Initialization
        ReadLock:=TCriticalSection.Create;
        WriteLock:=TCriticalSection.Create;
    Finalization
        ReadLock.Free;
        WriteLock.Free;
    end.这是使用READFILEEX、WRITEFILEEX的线程代码,在WINDOW2000下测试通过,当可使用的内存越大拷贝的速度越快,各位可以实验一下,这个恢复中的代码放在你的DEMO的主窗体里,窗体名称改为MAINFORM即可。