Einzelnen Beitrag anzeigen

Dunedain
(Gast)

n/a Beiträge
 
#1

[BCB5] Datei in einem Thread kopieren: ProgressBar Probleme

  Alt 1. Sep 2006, 19:22
Hallo,
brauche mal wieder eure Hilfe. Hab mir ein Programm geschrieben, dass zwei Verzeichnisse synchronsiert.
Während dem Synchronisierungsvorgang, welcher in einem einzelnen Thread abläuft, möchte ich den Gesamtstatus des Synchronisierens, sowie den Kopierstatus der aktuellen Datei mit einer ProgressBar (JVCL v3.2 TJvXPProgressBar) anzeigen.
Dafür habe ich mich an einem Code Snippet von www.bytesandmore.de bedient, und es für den Thread angepasst.
Das Kopieren funzt tadelos, jedoch wird die ProgressBar nicht richtig(?), bzw. zu unregelmäßig(?) aktualisiert. ( Bei nem 1.4 GB Image wird die ProgressBar nur einmal aktualisiert, bei nem 700 MB Image is nach ca 50% schluss)
Nachfolgend mal der Code für den Kopiervorgang, sowie die über Synchronize aufgerufene Funktion, welche das Statusfenster bedient.


Code:
bool TSearchThread::FileCopy( AnsiString sSourceFile,
                              AnsiString sDestFile )
{

  bool bRetVal = false;        // Rückgabewert
  DWORD liBytesReadTotal = 0;  // Anz. der bereits kopierten Bytes
  int iBytesLastWrite = 0;     // Anz. der im aktuellen
                                // Schleifendurchlauf kopierten Bytes
  int iBytesLastRead = 0;      // Anz. der in Lesepuffer eingelesenen
                                // Bytes


  // Falls Namen der Ziel- und Quelldatei identisch, abbrechen:
  if( !sDestFile.AnsiCompareIC( sSourceFile ) ) return false;


  // Falls ein Verzeichnis als Name der Zieldatei übergeben wurde, Namen der
  // Quelldatei an den Verzeichnisnamen anhängen:
  int iAttr = FileGetAttr( sDestFile );
  if( iAttr == -1 && (iAttr & faDirectory) == iAttr )
  {
 
    sDestFile = sDestFile + ExtractFileName( sSourceFile );
   
  }


  // Unterverzeichnis im Zielverzeichnis anlegen, falls das geforderte
  // Verzeichnis nicht existiert
  AnsiString sDir = ExtractFileDir( sDestFile );
  if(!Jvvcl5utils::DirectoryExists( sDir ) )
  {
 
    Jvvcl5utils::ForceDirectories( sDir );
   
  }


  // Quelldatei öffnen:
  iSourceHandle = FileOpen( sSourceFile.c_str(),
                            fmOpenRead | fmShareDenyWrite );
  if( iSourceHandle > 1 )
  {
 
    // Die Dateigrösse ermitteln:
    ulFileSize = FileSeek( iSourceHandle, 0, 2 );
    FileSeek( iSourceHandle, 0, 0 );


    if( ulFileSize != -1 )
    { 
   
      // Anzeige zurücksetzen:
      iCopyStatus = 0;
      Synchronize( Status );
      Application->ProcessMessages();


      // Zieldatei öffnen:
      iTargetHandle = FileCreate( sDestFile.c_str() );
      if( iTargetHandle >= 0 )
      {
     
        // Schreib- / Lesepuffer erzeugen:
        char *cpBuffer = new char[ iBufferSize ];
        if( cpBuffer )
        {
       
          bRetVal = true;


          while( liBytesReadTotal < ulFileSize )
          {
         
            // Daten aus der Quelldatei in den Puffer lesen:
            iBytesLastRead = FileRead( iSourceHandle, cpBuffer, iBufferSize );


            // Fehler aufgetreten:
            if( iBytesLastRead == -1 )
            {
           
              bRetVal = false;
             
            }
            // Falls Daten eingelesen:
            else if( iBytesLastRead != 0 )
            {
           
              // Daten aus dem Puffer in die Zieldatei schreiben:
              iBytesLastWrite = FileWrite( iTargetHandle, cpBuffer, iBytesLastRead );

              // Falls Anzahl der gelesenen Bytes != der Anzahl der geschriebenen...
              if( iBytesLastRead != iBytesLastWrite ) bRetVal = false;

              liBytesReadTotal += iBytesLastWrite;
             
            }


            // Fortschritt anzeigen:
            // Hier wird vermutlich der Fehlerteufel gewütet haben :|
            if( ( ( liBytesReadTotal * 100 / ulFileSize ) >= ( iCopyStatus + 1 )
               || iBytesLastRead != iBytesLastWrite
               || liBytesReadTotal == ulFileSize ) )
            {
                             
              iCopyStatus = liBytesReadTotal * 100 / ulFileSize;
              Synchronize(Status);
             
            }


            Application->ProcessMessages();
            if( !bRetVal ) break;
           
          }
         
          delete [] cpBuffer;
         
        }   


        // Dateien schliessen:
        FileClose( iSourceHandle );
        FileClose( iTargetHandle );


        // WinAPI
        // Falls keine Fehler aufgetreten
        // Zeitstempel übernehmen
        if( bRetVal )
        {
       
          FILETIME ftCreate, ftAccess, ftWrite;

          // Quelldatei zum lesen des Dateidatums öffnen
          hSource = CreateFile( sSourceFile.c_str(),
                                GENERIC_READ,
                                FILE_SHARE_READ,
                                0,
                                OPEN_EXISTING,
                                0,
                                0);


          // Handle der Quelldatei überprüfen
          if( hSource )
          {   
             
            // Zieldatei zum schreiben des Dateidatums öffnen
            hTarget = CreateFile( sDestFile.c_str(),
                                  GENERIC_WRITE,
                                  FILE_SHARE_READ,
                                  0,
                                  OPEN_EXISTING,
                                  0,
                                  0);


            // Handle der Zieldatei überprüfen
            if( hTarget )
            {
              GetFileTime( hSource, &ftCreate, &ftAccess, &ftWrite );
              bRetVal = SetFileTime( hTarget, &ftCreate, &ftAccess, &ftWrite );


              // Datei wieder schliessen
              CloseHandle( hTarget );
            }
            else
            {
              bRetVal = false;
            }

            // Datei wieder schliessen
            CloseHandle( hSource );
           
          }
          else
          {
         
            bRetVal = false;
           
          }
        }


        if( !bRetVal )
        {
       
          // Erstellte Dateiteile bei aufgetretenem Fehler
          // entfernen
          DeleteFile( sDestFile );
         
        }
       
      }
     
    }
    else
    {
   
      FileClose( iSourceHandle );
     
    }
  }
 
  return bRetVal;
 






void __fastcall TSearchThread::Status( void )
{

    // ProgressBar aktualisieren
    // -> prüfen, ob Aktualisierung notwendig
    // => nur notwendig, wenn sich die Position geändert hat
    if( formStatus->progressbarStatus->Position != iStatus )
    {
           
        formStatus->progressbarStatus->Position = iStatus;
        formStatus->progressbarStatus->Update();
       
    }


    // ProgressBar aktualisieren
    // -> prüfen, ob Aktualisierung notwendig
    // => nur notwendig, wenn sich die Position geändert hat
    if( formStatus->progressbarCopyStatus->Position != iCopyStatus )
    {
   
        formStatus->progressbarCopyStatus->Position = iCopyStatus;
        formStatus->progressbarCopyStatus->Update();
       
    } 
   

    // Status Bar aktualisieren
    // -> prüfen, ob Aktualisierung notwendig
    // => nur notwendig, wenn sich der Text geändert hat
    if( formStatus->statusbarStatus->SimpleText != sStatus )
    {
   
        formStatus->statusbarStatus->SimpleText = sStatus;
        formStatus->statusbarStatus->Update();
       
    }


    // Dateianzahl anzeigen
    // -> prüfen, ob Aktualisierung notwendig
    // => nur notwendig, wenn sich der Text geändert hat
    if( formStatus->labelStatusMax->Caption !=
        AnsiString( slFileNames->Count ) )
    {

        formStatus->labelStatusMax->Caption = AnsiString( slFileNames->Count );
        formStatus->labelStatusMax->Update();
   
    }


    // Dateigröße anzeigen  
    // -> prüfen, ob Aktualisierung notwendig
    // => nur notwendig, wenn sich der Text geändert hat
    if( formStatus->labelCopyStatusMax->Caption != AnsiString( ulFileSize ) )
    {

         formStatus->labelCopyStatusMax->Caption = AnsiString( ulFileSize );
         formStatus->labelCopyStatusMax->Update();
   
    }


    Application->ProcessMessages();
}

Auch hier am Ende nochmal der Hinweis, dass Programmieren NUR ein Hobby von mir ist, daher bin ich nicht nur für Rat und Tat zum Fehler, sondern auch für Anregungen zum Programmierstiel dankbar (sofern so etwas bei mir erkennbar ist).

Btw, Schönes Wochenende
  Mit Zitat antworten Zitat