AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein [BCB5] Datei in einem Thread kopieren: ProgressBar Probleme
Thema durchsuchen
Ansicht
Themen-Optionen

[BCB5] Datei in einem Thread kopieren: ProgressBar Probleme

Ein Thema von Dunedain · begonnen am 1. Sep 2006 · letzter Beitrag vom 3. Sep 2006
Antwort Antwort
Dunedain
(Gast)

n/a Beiträge
 
#1

[BCB5] Datei in einem Thread kopieren: ProgressBar Probleme

  Alt 1. Sep 2006, 18: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
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.137 Beiträge
 
Delphi 12 Athens
 
#2

Re: [BCB5] Datei in einem Thread kopieren: ProgressBar Probl

  Alt 1. Sep 2006, 18:47
hab's zwar nich so mit C, aber etwas könnte man wohl dennoch ändern.

Code:
if(!Jvvcl5utils::DirectoryExists( sDir ) )
{
  Jvvcl5utils::ForceDirectories( sDir );
}
ForceDirectories prüft intern selber nochmal, also kann das ganze IF-Zeugs weg.

dieses sollte man vermutlich auch nicht direkt im Thread aufrufen ... kann also weg:
Code:
Application->ProcessMessages();
in TSearchThread::Status könnten och einige IFs entfallen, da hier wiederrum die Komponenten intern oftmals selber prüfen, ob wirklich was zu ändern ist.

Code:
void __fastcall TSearchThread::Status( void )
{
    formStatus->progressbarStatus->Position = iStatus;
    formStatus->progressbarCopyStatus->Position = iCopyStatus;
    formStatus->statusbarStatus->SimpleText = sStatus;
    formStatus->labelStatusMax->Caption = AnsiString( slFileNames->Count );
    formStatus->labelCopyStatusMax->Caption = AnsiString( ulFileSize );
    Application->ProcessMessages();
}

// statt Application->ProcessMessages(); eventuell
formStatus->update;
//oder ???
formStatus->refresh;
//oder auch mehreres davon


ich weiß ja nicht wie C das mit den Klammern so handhabt, aber eventuell hilft es ja auch selber ein Paar vorzuschreiben
Code:
// Fortschritt anzeigen:
if ( ( ( liBytesReadTotal * 100 / ulFileSize ) > iCopyStatus )
    || ( iBytesLastRead != iBytesLastWrite )
    || ( liBytesReadTotal == ulFileSize ) )
{

    iCopyStatus = liBytesReadTotal * 100 / ulFileSize;
    Synchronize(Status);

}
oder nur so?
Code:
// Fortschritt anzeigen:
if ( ( liBytesReadTotal * 100 / ulFileSize ) > iCopyStatus )
{

    iCopyStatus = liBytesReadTotal * 100 / ulFileSize;
    Synchronize(Status);

}
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Dunedain
(Gast)

n/a Beiträge
 
#3

Re: [BCB5] Datei in einem Thread kopieren: ProgressBar Probl

  Alt 1. Sep 2006, 19:16
Danke für die schnelle Antwort.

Hab deine Vorschläge sofort umgesetzt.
Leider funzt das mit der ProgressBar immer noch nicht richtig


Die ifs in TSearchThread::Status waren nicht zur Überprüfung ob was geändert werden sollte, sondern nur um herauszufinden, welche Elemente sich geändert haben und welche deshalb aktualisiert werden sollten (->Update()).

Hab deinen Vorschlag aber trotzdem umgesetzt, da dass ProcessMessages ebenfalls das Formular aktualisiert...
  Mit Zitat antworten Zitat
Dunedain
(Gast)

n/a Beiträge
 
#4

Re: [BCB5] Datei in einem Thread kopieren: ProgressBar Probl

  Alt 3. Sep 2006, 12:07
Da bin ich wieder.

Ich weiß zwar net warum, aber jetzt funzt es...

Hab aber noch ne Frage zum kopieren von Dateien. Ich verwende für das Kopieren einen Puffer von 8192. Jetzt stellt sich mir jedoch die Frage, ob ich den Puffer für große Dateien vergrößern sollte? Also beispeilsweise auf 32768 oder noch größer...?

Bringt das was bei der Kopiergeschwindigkeit bzw. ist das prinzipiell überhaupt sinnvoll?
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:45 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz