![]() |
[BCB5] Datei in einem Thread kopieren: ProgressBar Probleme
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 ![]() 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 :) |
Re: [BCB5] Datei in einem Thread kopieren: ProgressBar Probl
hab's zwar nich so mit C, aber etwas könnte man wohl dennoch ändern.
Code:
ForceDirectories prüft intern selber nochmal, also kann das ganze IF-Zeugs weg.
if(!Jvvcl5utils::DirectoryExists( sDir ) )
{ Jvvcl5utils::ForceDirectories( sDir ); } dieses sollte man vermutlich auch nicht direkt im Thread aufrufen ... kann also weg:
Code:
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.
Application->ProcessMessages();
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 :gruebel:
Code:
oder nur so?
// Fortschritt anzeigen:
if ( ( ( liBytesReadTotal * 100 / ulFileSize ) > iCopyStatus ) || ( iBytesLastRead != iBytesLastWrite ) || ( liBytesReadTotal == ulFileSize ) ) { iCopyStatus = liBytesReadTotal * 100 / ulFileSize; Synchronize(Status); }
Code:
// Fortschritt anzeigen:
if ( ( liBytesReadTotal * 100 / ulFileSize ) > iCopyStatus ) { iCopyStatus = liBytesReadTotal * 100 / ulFileSize; Synchronize(Status); } |
Re: [BCB5] Datei in einem Thread kopieren: ProgressBar Probl
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... |
Re: [BCB5] Datei in einem Thread kopieren: ProgressBar Probl
Da bin ich wieder.
Ich weiß zwar net warum, aber jetzt funzt es... :roll: 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? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:31 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz