![]() |
Delphi-Version: XE5
TPath.Combine, TPath.GetTempPath threadsicher?
Ich nutzte folgenden Code, um eine Resource in das Filesystem zu schreiben.
Da alles im Hintergrund laufen soll, habe ich das in einen Thread gepackt. Leider bricht mir dann mein Tablet mit Meldung "Anwendung wurde beendet" nach einiger Zeit ab. Ich habe dann testweise TPath.GetTempPath gegen den Pfad als String getauscht und nun scheint es zu laufen. Ist denn TPath eine visuelle Komponente, oder wie kann man sich das Problem erklären?
Delphi-Quellcode:
//kopiert einen Song als Resource in eine Datei
Function CopyStream2File(ResourceID: string; var fName: String): boolean; var ResStream: TResourceStream; begin Result := False; ResStream := TResourceStream.Create(HInstance, ResourceID, RT_RCDATA); try //MP3 File aus Resource laden und in Filesystem ablegen fName := TPath.Combine(TPath.GetTempPath, 'tmp.mp3'); // fName := TPath.Combine('/data/data/com.embarcadero.Meinprogram/files/', 'tmp.mp3'); ResStream.Position := 0; ResStream.SaveToFile(fName); Result := True; finally ResStream.Free; end; end; |
AW: TPath.Combine, TPath.GetTempPath threadsicher?
TPath.GetTempPath selber ist threadsave, aber wie es mit
![]() ![]() Aber warum kommt keiner auf die Idee diesen Wert in einer globalen Veriable zwischenzuspeichern oder kann es denn passieren, daß sich dieser Wert jemals ändern wird? :stupid: Und was sind das für Threads und wie behandelst du die Exceptions darin? PS: Warum ist fName ein VAR-Parameter? Und Result=False wird es niemals geben. |
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Zitat:
Damit man außen in einem Log FName ausgeben kann. Klar gibt es Result=false... bei einer Exception. GlaskugelMode.Active := false; |
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Zitat:
Zitat:
Zitat:
|
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Zitat:
Also könntest Du außen die Exception abfangen und Result weg lassen oder must noch ein try except drum setzen. Mavarik |
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Zitat:
Soll also bei einer auftretenden Exception lediglich ein false zurückgegeben werden, würde sich dieses Konstrukt anbieten:
Delphi-Quellcode:
Roter Kasten: Wie Mavarik korrekt bemerkt.
//kopiert einen Song als Resource in eine Datei
Function CopyStream2File(ResourceID: string; var fName: String): boolean; var ResStream: TResourceStream; begin try ResStream := TResourceStream.Create(HInstance, ResourceID, RT_RCDATA); try //MP3 File aus Resource laden und in Filesystem ablegen fName := TPath.Combine(TPath.GetTempPath, 'tmp.mp3'); ResStream.Position := 0; ResStream.SaveToFile(fName); Result := True; finally ResStream.Free; end; except result := false; end; end; |
AW: TPath.Combine, TPath.GetTempPath threadsicher?
@GlaskugelMode:
Wie gerade schon jemand sagte: Es gibt entweder True oder eine Exception. Bei einer Exception wird mit der Panzerfaust reingeschossen, man fliegt an der Result-Rückgabe vorbei, direkt zum nächsten Try-Except und es gibt somit kein Result. Im Prinzip funktioniert die gezeigte Lösung, auch wenn es nicht wirklich "optiomal" ist, wenn die Exception so abgefangen, dann einfach verworfen und in einen nichtssagenden Boolean verwandelt wird. * Exception abfangen und als Boolean zurückgeben, dann aber bitte mit Zusatzinfox ala GetLastError * oder als Fehlercode zurückgeben (die Fehler/Exception sprechend umwandeln) * oder eben ohne Fehlerrückgabe-Wert und dafür mit Exceptions arbeiten [add] Lach .... die RedBox lebt mal wieder :thumb: |
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Zitat:
Zum Beispiel so:
Delphi-Quellcode:
oder
Function CopyStream2File(ResourceID: string; var fName: String): boolean;
var ResStream: TResourceStream; begin Result := False; try ResStream := TResourceStream.Create(HInstance, ResourceID, RT_RCDATA); try //MP3 File aus Resource laden und in Filesystem ablegen fName := TPath.Combine(TPath.GetTempPath, 'tmp.mp3'); // fName := TPath.Combine('/data/data/com.embarcadero.Meinprogram/files/', 'tmp.mp3'); ResStream.Position := 0; ResStream.SaveToFile(fName); Result := True; finally ResStream.Free; end; except end end;
Delphi-Quellcode:
var
FName : String; error : boolean; begin ... try error := CopyStream2File('42',FName); except MyError('Fehler...'); end; if not Error then Play(FName) end; |
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Ich habe nun eure Meinungen verstanden und etwas dazugelernt.
Aber was hat es mit dem roten Kasten auf sich? |
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Zitat:
(Na, wer hatte Ihn dieses mal?) So wäre wahrscheinlich die bevorzugte Lösung:
Delphi-Quellcode:
Auch wenn ich es immer so mache wie in meinen 1. Posting...
Function CopyStream2File(ResourceID: string): String;
var ResStream: TResourceStream; begin ResStream := TResourceStream.Create(HInstance, ResourceID, RT_RCDATA); try //MP3 File aus Resource laden und in Filesystem ablegen Result := TPath.Combine(TPath.GetTempPath, 'tmp.mp3'); ResStream.Position := 0; ResStream.SaveToFile(fName); finally ResStream.Free; end; end; var FName : String; begin try FName := CopyStream2File('42'); Play(FName); except end; end; Mavarik |
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Sehr grausam, wie hier manche mit den Exceptions umgehen ... indem man versucht diese mit aller Gewalt zu umgehen :roll:
Das ist doch absoluter Schwachfug und führt einzig und alleine dazu, dass irgendwas nicht funktioniert, aber keiner merkt es.
Delphi-Quellcode:
Wann passiert es denn, dass ich hier eine Exception bekomme?
Function CopyStream2File(ResourceID: string): String;
var ResStream: TResourceStream; begin ResStream := TResourceStream.Create(HInstance, ResourceID, RT_RCDATA); try //MP3 File aus Resource laden und in Filesystem ablegen Result := TPath.Combine(TPath.GetTempPath, 'tmp.mp3'); ResStream.Position := 0; ResStream.SaveToFile(fName); finally ResStream.Free; end; end; begin Play( CopyStream2File('42') ); end;
Exceptions sind nicht böse, sondern sehr hilfreich. Und wenn man die Exceptions wirklich nicht anzeigen möchte, dann geht das ganz simpel, indem man ![]() |
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Zitat:
Delphi-Quellcode:
aus zu setzen?
var
FName : String; error : boolean; begin ... try error := CopyStream2File('42',FName); except MyError('Fehler...'); end; if not Error then Play(FName) end; Von mir aus auch
Delphi-Quellcode:
var
FName : String; error : integer; begin ... try error := CopyStream2File('42',FName); except MyError('Fehler...',error); end; if Error=0 then Play(FName) end; |
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Ganz einfach das hier:
Delphi-Quellcode:
Und wenn wir diese initiale Zuweisung von
var
FName : String; error : boolean; begin ... error := False; // damit das auf jeden Fall initialisiert ist try error := CopyStream2File('42',FName); // <- das erzeugt eine Exception except MyError('Fehler...'); // <- Ja wird ausgeführt end; if not Error then // <- Was für einen Wert hat jetzt Error? Richtig: False - äh, aber das ist doch Falsch! Eben darum Play(FName) end;
Delphi-Quellcode:
weglassen, dann haben wir einen Zufallsgenerator. Mal wird
error := False;
Delphi-Quellcode:
ausgeführt und mal nicht, obwohl es immer einen Fehler gibt. Dadurch kommen dann solche Gerüchte über Auswirkungen von Erdstrahlen oder Sonnenflecken auf die Programme auf.
Play(FName)
|
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Ohne es nachgeprüft zu haben, aber könnte es sein das TPath.GetTempPath den Pfad ohne abschliessenden Slash bzw. Backslash zurückgibt?
|
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Zitat:
Delphi-Quellcode:
verwirren lassen, es wird trotzdem ein Directory zurückgeliefert und eben kein Path), spielt aber keine Geige, denn es wird ja
Get...Path
Delphi-Quellcode:
benutzt, und das sorgt dafür, dass der richtige Trenner dazwischen kommt.
TPath.Combine
|
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Zitat:
Deswegen so
Delphi-Quellcode:
Schon habe ich ein Error-Free Programm/Procedure und ob und wie ich den Fehler ausgeben will kann ich außerhalb anhand meines Boolean entscheiden...
Function CopyStream2File(ResourceID: string; var fName: String): boolean;
var ResStream: TResourceStream; begin Result := False; try ResStream := TResourceStream.Create(HInstance, ResourceID, RT_RCDATA); try //MP3 File aus Resource laden und in Filesystem ablegen fName := TPath.Combine(TPath.GetTempPath, 'tmp.mp3'); // fName := TPath.Combine('/data/data/com.embarcadero.Meinprogram/files/', 'tmp.mp3'); ResStream.Position := 0; ResStream.SaveToFile(fName); Result := True; finally ResStream.Free; end; except end end; |
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Und da steht dann "Es ist ein Fehler aufgetreten", da man die Exception einfach geschluckt hat und somit nicht weiß, welche überhaupt geworfen wurde, geschweige denn ihren ggf. vorhandenen Fehlertext gespeichert hat.
|
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Und wenn man so etwas mit aller Gewalt haben will, dann sollte man das auch sprachlich entsprechend hervorheben, damit man auch später noch weiß, dass da etwas in die Hose gehen kann, ohne dass man eine Exception bekommt:
Delphi-Quellcode:
Jetzt kann man das wahlweise mit oder ohne Exception-Behandlung benutzen:
Function CopyResourceToFile( const ResourceID: string ) :String);
var ResStream: TResourceStream; begin ResStream := TResourceStream.Create(HInstance, ResourceID, RT_RCDATA); try //MP3 File aus Resource laden und in Filesystem ablegen fName := TPath.Combine(TPath.GetTempPath, 'tmp.mp3'); ResStream.Position := 0; ResStream.SaveToFile(fName); finally ResStream.Free; end; end; function TryCopyResourceToFile( const ResourceID: string; out AFileName : string ) : Boolean; begin try AFileName := CopyResourceToFile( ResourceId ); Result := True; except Result := False; end; end;
Delphi-Quellcode:
// mit Exception
Play( CopyResourceToFile( '42' ) ); // oder ganz bewusst im Code auf die Exception verzichten if TryCopyResourceToFile( '42', FName ) then Play( FName ); |
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Zitat:
Indem ich mir genau wie die WinAPI nen GetMyLastError baue oder was? :kotz: |
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Meine Rede. Ich freu mich auch immer in der Hotline, wenn solche ominösen Fehlermeldungen auftauchen, weil man ja ganz schlau mit Exceptions umgegangen ist.
|
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Bevor das hier ganz in Richtung Off-Topic abdriftet - hat noch irgendjemand Erkenntnisse zu der eigentlichen Frage?
Insbesondere wäre vom Fragesteller ein Hinweis nützlich, welche Umgebung hier eigentlich vorliegt: Windows, OSX, iOS, Android? |
AW: TPath.Combine, TPath.GetTempPath threadsicher?
Zitat:
Danke nochmals für eure Erklärungen. Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:04 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