我的程序是类似于Flashget的功能,但下载的是整个目录下的所有文件。下载使用的是WinINet实现。整个系统的线程分维三级:MainThread用于任务检测(允许同时从多个服务器上的目录中下载文件)、JobThread任务线程(完成任务开始时的准备工作,如:尝试连接。测试完成后下载文件)、FtpThread下载线程(完成文件的下载工作)。
在一个任务线程工作时,同时可能会有9个下载线程工作,CPU占用最高达到90%(下载线程刚启动时),正常情况下也有20-30%。
我想问的是:Flashget也有大量的线程,但为何不是很耗Cpu资源,有没有好的解决办法?谢谢!!!

解决方案 »

  1.   

    我每隔线程是独立工作的,在使用公用数据时,使用了同步机制。现在关键的问题是为何占用如此多的CPU资源?
    我把线程的等级设低同样。
    请大家继续关注!
      

  2.   

    uses
      WinInet, ComCtrls;function FtpDownloadFile(strHost, strUser, strPwd: string;
      Port: Integer; ftpDir, ftpFile, TargetFile: string; ProgressBar: TProgressBar): Boolean;  function FmtFileSize(Size: Integer): string;
      begin
        if Size >= $F4240 then
          Result := Format('%.2f', [Size / $F4240]) + ' Mb'
        else
        if Size < 1000 then
          Result := IntToStr(Size) + ' bytes'
        else
          Result := Format('%.2f', [Size / 1000]) + ' Kb';
      end;const
      READ_BUFFERSIZE = 4096;  // or 256, 512, ...
    var
      hNet, hFTP, hFile: HINTERNET;
      buffer: array[0..READ_BUFFERSIZE - 1] of Char;
      bufsize, dwBytesRead, fileSize: DWORD;
      sRec: TWin32FindData;
      strStatus: string;
      LocalFile: file;
      bSuccess: Boolean;
    begin
      Result := False;  { Open an internet session }
      hNet := InternetOpen('Program_Name', // Agent
                            INTERNET_OPEN_TYPE_PRECONFIG, // AccessType
                            nil,  // ProxyName
                            nil, // ProxyBypass
                            0); // or INTERNET_FLAG_ASYNC / INTERNET_FLAG_OFFLINE  {
        Agent contains the name of the application or
        entity calling the Internet functions
      }
      { See if connection handle is valid }
      if hNet = nil then
      begin
        ShowMessage('Unable to get access to WinInet.Dll');
        Exit;
      end;  { Connect to the FTP Server }
      hFTP := InternetConnect(hNet, // Handle from InternetOpen
                              PChar(strHost), // FTP server
                              port, // (INTERNET_DEFAULT_FTP_PORT),
                              PChar(StrUser), // username
                              PChar(strPwd),  // password
                              INTERNET_SERVICE_FTP, // FTP, HTTP, or Gopher?
                              0, // flag: 0 or INTERNET_FLAG_PASSIVE
                              0);// User defined number for callback  if hFTP = nil then
      begin
        InternetCloseHandle(hNet);
        ShowMessage(Format('Host "%s" is not available',[strHost]));
        Exit;
      end;  { Change directory }
      bSuccess := FtpSetCurrentDirectory(hFTP, PChar(ftpDir));  if not bSuccess then
      begin
        InternetCloseHandle(hFTP);
        InternetCloseHandle(hNet);
        ShowMessage(Format('Cannot set directory to %s.',[ftpDir]));
        Exit;
      end;  { Read size of file }
      if FtpFindFirstFile(hFTP, PChar(ftpFile), sRec, 0, 0) <> nil then
      begin
        fileSize := sRec.nFileSizeLow;
        // fileLastWritetime := sRec.lastWriteTime
      end else
      begin
        InternetCloseHandle(hFTP);
        InternetCloseHandle(hNet);
        ShowMessage(Format('Cannot find file ',[ftpFile]));
        Exit;
      end;  { Open the file }
      hFile := FtpOpenFile(hFTP, // Handle to the ftp session
                           PChar(ftpFile), // filename
                           GENERIC_READ, // dwAccess
                           FTP_TRANSFER_TYPE_BINARY, // dwFlags
                           0); // This is the context used for callbacks.  if hFile = nil then
      begin
        InternetCloseHandle(hFTP);
        InternetCloseHandle(hNet);
        Exit;
      end;  { Create a new local file }
      AssignFile(LocalFile, TargetFile);
      {$i-}
      Rewrite(LocalFile, 1);
      {$i+}  if IOResult <> 0 then
      begin
        InternetCloseHandle(hFile);
        InternetCloseHandle(hFTP);
        InternetCloseHandle(hNet);
        Exit;
      end;  dwBytesRead := 0;
      bufsize := READ_BUFFERSIZE;  while (bufsize > 0) do
      begin
        Application.ProcessMessages;    if not InternetReadFile(hFile,
                                @buffer, // address of a buffer that receives the data
                                READ_BUFFERSIZE, // number of bytes to read from the file
                                bufsize) then Break; // receives the actual number of bytes read    if (bufsize > 0) and (bufsize <= READ_BUFFERSIZE) then
          BlockWrite(LocalFile, buffer, bufsize);
        dwBytesRead := dwBytesRead + bufsize;    { Show Progress }
        ProgressBar.Position := Round(dwBytesRead * 100 / fileSize);
        Form1.Label1.Caption := Format('%s of %s / %d %%',[FmtFileSize(dwBytesRead),FmtFileSize(fileSize) ,ProgressBar.Position]);
      end;  CloseFile(LocalFile);  InternetCloseHandle(hFile);
      InternetCloseHandle(hFTP);
      InternetCloseHandle(hNet);
      Result := True;
    end;
      

  3.   

    上面是老外的一个函数.....关于这个我原来也写过,好像没有办法解决CPU占用率较高的问题flashGet不是delphi写的吧:)关注
      

  4.   

    感谢:bluemeteor(挂月||╭∩╮(︶︿︶)╭∩╮) 
    我下载的部分已经完成,基本和上面的差不多。
    请大家继续关注!!!!
      

  5.   

    DELPHI启动线程时大量战胜CPU,但是启完之后应该不会呀。
      

  6.   

    在线程刚启动时比较占用Cpu,但在Ftp时业比较好资源.
      

  7.   

    我现在的解决办法是在线程下载完一个文件后(不同的线程下载不同的文件)Sleep(1000),Cpu占用情况稍好一点.以前使用Sleep(10).
    不知该种方法妥当吗?
    请大家继续关注!!!