Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   SHFileoperatio-Ärger (https://www.delphipraxis.net/175843-shfileoperatio-aerger.html)

Mattze 23. Jul 2013 14:09

SHFileoperatio-Ärger
 
Hallo,

ich kriege es einfach nicht hin.
Früher (winXP) war SHFileOperation multithreaded. Heute nicht mehr (win7,8 32,64, pro).
Früher habe ich es aufgerufen und dann ging es in meinem Programm weiter. Kopiert wurde im Hintergrund. Ich konnte sogar das Copy nochmals anstoßen usw.
Das kriege ich jetzt nicht mehr hin. Der win Explorer tut es aber. Evtl. nutzt der aber auch IFileOperation. Nur, dieses Interface habe ich in D7 pro (SHLObj) noch nicht definiert (erst ab Delphi 2010).
Was tun?
Hat jemand einen Tipp für mich (außer einer neueren Delphi-Version!).
Wie kann ich das Copy threaded machen?

Gruß
Mattze

sx2008 23. Jul 2013 17:58

AW: SHFileoperatio-Ärger
 
Zitat:

Zitat von Mattze (Beitrag 1222391)
Früher (winXP) war SHFileOperation multithreaded

Kann ich mir nicht vorstellen.
1.) es gibt kein CopyAsynch-Flag oder vergleichbares Flag
2.) die Funktion SHFileOperation liefert einen einfachen Rückgabewert
Code:
Return value
Type: int
Returns zero if successful; otherwise nonzero.
Kein Hinweis darauf, dass die Funktion asynchon arbeiten könnte
3.) in der Struktur SHFILEOPSTRUCT gibt es das Bool-Flag fAnyOperationsAborted, das von SHFileOperation gesetzt wird.
Würde SHFileOperation sofort zurückkehren und intern Threads starten um die Operation zu bewerkstelligen, dann hätte niemand die Möglichkeit um festzustellen ob die Kopier-/Lösch- oder Move-Operation wirklich beendet ist.
Das Flag fAnyOperationsAborted wäre sinnlos, weil man nicht sicher feststellen kann ob der Wert gültig ist.

Mattze 23. Jul 2013 19:53

AW: SHFileoperatio-Ärger
 
Hallo,

nun,darüber will ich nicht streiten. Es geht nicht darum!
Vielleicht war der Systemdialog zum Kopieren auch nur nicht modal und jetzt ist er es. (So was habe ich mal gelesen.)
Fakt ist, dass nach einem Aufruf von SHFileOperation sofort zum Hauptprogramm zurückgekehrt wurde und ich dort beliebig weiterarbeiten konnte. Und sei es, dass ich weitere SHFileOperation(s) angestoßen habe.
Das geht jetzt nicht mehr und das hätte ich gerne wieder. Es stört doch sehr, dass das Hauptprogramm steht, wenn man nur etwas kopiert, bis das Copy erledigt ist.
Irgendwelche Ideen?

Gruß
Mattze

CCRDude 24. Jul 2013 08:44

AW: SHFileoperatio-Ärger
 
Selber Kopieroperation als getrennten Thread abspalten?

Mattze 24. Jul 2013 08:58

AW: SHFileoperatio-Ärger
 
Hallo,

tschja, ganz so einfach ist das nicht wegen der "CopyThreadVerwaltung". Es können ja sehr viele sein...
Ich versuche mir gerade so was zu basteln.
Einen "CopyThread und "ThreadCopyManager", in dem sich jeder "CopyThread" mit seinem Handle verewigt - solange er aktiv ist.
Warum? Nur erst mal ein Problem: Wenn das Hauptprogramm geschlossen werden soll und noch kopiert wird, soll das natürlich nicht einfach abgebrochen werden.
Aber ich bin mir sicher, dass da noch weitere Probleme lauern... ;-)

Gruß
Mattze

jaenicke 24. Jul 2013 09:46

AW: SHFileoperatio-Ärger
 
Dieser "Kopiermanager" könnte dann auch gleich dafür sorgen, dass nicht mehrere Kopiervorgänge parallel laufen, sondern dass diese nacheinander abgearbeitet werden um das ganze zu beschleunigen. Dann reicht da auch ein Thread, der immer mit den Vorgängen gefüttert wird.

CCRDude 24. Jul 2013 10:25

AW: SHFileoperatio-Ärger
 
Zitat:

Zitat von Mattze (Beitrag 1222452)
Nur erst mal ein Problem: Wenn das Hauptprogramm geschlossen werden soll und noch kopiert wird, soll das natürlich nicht einfach abgebrochen werden.

Das gäb's aber immer :)
  • Ohne Threads würde das Hauptfenster nicht reagieren, das verleitet Benutzer zum Abschießen...
  • Bei jedem Thread, den Du implementierst, musst Du diese Situation berücksichtigen.

Als simplen Workaround (der aber nicht so schön wäre wie die von jaenicke genannte Queue) könntest Du ein Hilfsprozess beilegen, den Du für jeden Kopierjob startest. Der läuft weiter, parallel (weil eigener Prozess) und auch noch wenn das Hauptprogramm geschlossen wird.

Mattze 24. Jul 2013 10:57

AW: SHFileoperatio-Ärger
 
Hallo,

das nacheinander Abarbeiten wäre eine Idee.
Es gibt nämlich noch ein größeres Problem (für mich mit D7):
"Dynamische Variable"
Da man vorher ja nicht weiß, wie oft der User den Kopiervorgang (per Thread) anstößt, also nicht weiß, wie viele Threads gestartet werden, kann man die Threadvariable nicht "vordefinieren" (was auch aus Platz- und Performancegründen sicherlich nicht schön wäre).
Ich kenne aber keine Möglichkeit, Variable während der Laufzeit zu erzeugen. Gibt es da was und das ist mir nur entgangen?
Wenn ich das nacheinander mache, brauche ich aber nur eine Threadvariable.
Und wenn ich den Thread nur über seinen Handle (oder ThreadID) anspreche (per API), brauche ich auch nur eine Variable - nehme ich an. Deshalb auch der "CopyThreadManager". Der hält eine Liste mit den Threadhandlen vor.


Gruß
Mattze

CCRDude 24. Jul 2013 11:25

AW: SHFileoperatio-Ärger
 
Hmm... das Problem verstehe ich nicht ganz.

Delphi-Quellcode:
var a: array of TMyThread;
begin
   SetLength(a, 4);
end;
geht nicht unter D7? Ansonsten... TList, gibt es das schon unter D7? Mindestens eine TStringList gibt es da, mit Objekten an jeder Zeile, als unschönen Workaround, wobei ich glaube, dass es eigentlich auch die anderen Dinge (dynamische Arrays und TList) geben dürfte.

p80286 24. Jul 2013 11:34

AW: SHFileoperatio-Ärger
 
Das geht!

Gruß
K-H

Mattze 24. Jul 2013 11:41

AW: SHFileoperatio-Ärger
 
Hallo,

die Methode kenne ich natürlich auch.
Finde ich hier aber nicht so schön bzw. aufwendiger.
Z. Bsp. möchte ich gerne fertige Threads auch rauslöschen.
Bei solchen Arrays müsste ich da umspeichern usw.
Außerdem wäre da mehr Speicherplatz von Nöten, weil ich eben die ganze Klasse TMyThread im Array halte.
Wenn ich eine TList habe, in der ich die Handles der Threads ablege, ist das Rauslöschen, Thread finden... alles kein Problem!
Halte ich HIER für die günstigere Variante.

Gruß
Mattze

@K-H: Und wie? (Außer mit den dynamischen Arrays von oben.)

jaenicke 24. Jul 2013 12:42

AW: SHFileoperatio-Ärger
 
Zitat:

Zitat von Mattze (Beitrag 1222470)
Z. Bsp. möchte ich gerne fertige Threads auch rauslöschen.
Bei solchen Arrays müsste ich da umspeichern usw.

Dir ist aber schon klar, dass TList intern ein array of Pointer nutzt?

Mattze 24. Jul 2013 13:44

AW: SHFileoperatio-Ärger
 
Hallo,

ist mir schon klar.
Ich bin nur sehr faul und da kommt es mir entgegen, dass TList einen Haufen Dinge zur Verfügung stellt, die ich sonst alle selber coden müsste.
Wer weiß, ob ich das richtig hinkriegen und wie lange das dauern würde.
Im Grunde brauche ich ja nur eine Liste von 32-Integer. Soweit ich weiß, ist da TList die beste Variante.

Gruß
Mattze

hathor 25. Jul 2013 21:55

AW: SHFileoperatio-Ärger
 
Schon mal Microsoft's free RoboCopy getestet?
...es ist in den Windows-Versionen ab Vista, also auch in Windows Servern 2008 standardmäßig dabei und kann direkt aus der Kommandozeile heraus bzw. in der Powershell verwendet werden.

http://de.wikipedia.org/wiki/Robocopy
GUI: http://www.chip.de/downloads/Robocop..._28220207.html

Mattze 26. Jul 2013 05:29

AW: SHFileoperatio-Ärger
 
Hallo,

Robocopy wäre sicherlich eine Alternative.
Ich hätte das bloß gerne direkt als Programmierschnittstelle.

Ein externes Programm aufzurufen, finde ich nicht soo toll.

Also, ein Interface oder ähnliches für Delphi (7 prof) - das wär's!
Gibt's sowas? Ich habe noch nix gefunden.

Gruß
Mattze

Mattze 27. Jul 2013 13:48

AW: SHFileoperatio-Ärger
 
Hallo,

so, das scheint einigermaßen zu klappen. Mal sehen, wie das in der normalen Arbeit ist...
Es bleibt aber ein Problem:
Wie kriege ich das bei DnD hin?
Per MouseHook? Abfangen und meine MultiThread-Lösung rein? Geht das überhaupt? Habe noch nie mit einem Hook "gespielt". War bisher einfach nicht nötig!
Was meint Ihr? Wie geht's am besten?

Gruß
Mattze

jaenicke 27. Jul 2013 15:57

AW: SHFileoperatio-Ärger
 
Drag and Drop? Wie meinst du das?
Dort, wo du die Behandlung startest, kannst du das doch entsprechend umsetzen. Ich verstehe nicht wo du da die Notwendigkeit für einen Hook siehst.

Mattze 27. Jul 2013 17:07

AW: SHFileoperatio-Ärger
 
Hallo,

ich sehe das auch nicht, aber ich weiß nicht, wie ich das sonst machen soll.
Ich nutze eine Komponente (VirtualTreeview, genauer: VirtualExplorerEasyListview),
die DnD offenbar über SHFileOperation selber bastelt.
Und da ist das eben nicht mehr multithreaded.
Die Frage ist also, wie ich das da abfange und, wenn ich in der Source rumfummle, ob ich da wirklich alles finde.
Ich fände es günstiger, wenn ich es vollständig selber machen könnte, also das DnD vor der Komponente abfangen könnte.

Vielleicht würde es ja auch ausreichen, dass Copywindow von Windows nicht modal zu machen. Irgendwo habe ich mal sowas gelesen, dass das der eigentliche Grund für die Probleme wäre.

Gruß
Mattze

Mattze 28. Jul 2013 10:01

AW: SHFileoperatio-Ärger
 
Hallo,

ich überlege hin und her und kriege es nicht raus. Es geht nicht um DnD, sondern das davor!
Ich erzeuge den Thread ohne Variable einfach mit "TMyThread.create(false)".
Den Handle des Threads speichere ich mit in einer TList (TCList.add(Pointer(self.handle)) in TMyThread.create).

Gibt Delphi den Thread nun bei Programmende selber frei (auch ohne Variable) oder muss ich das von Hand im OnClose (oder OnCloseQuery) des Hauptformulars machen?
Delphi-Quellcode:
      for a:=0 to TCListe.Count-1 do begin
        terminatethread(Cardinal(TCListe[a]),i);
        waitforsingleobject(Cardinal(TCListe[a]),300);
        closehandle(Cardinal(TCListe.items[a]))
      end;
Die Frage gilt für D7 prof.

Gruß
Mattze

CCRDude 31. Jul 2013 11:51

AW: SHFileoperatio-Ärger
 
Delphi gibt den Thread nur dann frei (nicht bei Programmende sondern Threadablaufende), wenn dieser FreeOnTerminate gesetzt hat.

Warum speicherst Du nicht die Thread-Objekte selber in der Liste?

Mattze 1. Aug 2013 09:50

AW: SHFileoperatio-Ärger
 
Hallo CCRDude,

FreeOnTerminate ist schon klar, aber die Frage war etwas anders.
Funktioniert das evtl. nur, wenn der Thread mit einer Variable im Hauptprogramm "angemeldet" ist?
Es kann - und wird bestimmt auch - prinzipiell funktionieren. Aber denkbar wäre auch so eine (falsche) Einschränkung.

Mit der automatischen Freigabe der Threads ist das so eine Sache. Manchmal führt das tatsächlich zu einem Speicherleck. (Ich nehme an, immer dann, wenn man im Thread etwas createt hat und es im Thread.destroy nicht frei gibt - oder geben kann. Z. Bsp. bei SHFileOperation. Da scheint einiges angelegt zu werden und erst bei Beendigung oder Cancel wieder frei gegeben zu werden. Im Thread.destroy kommt man da nicht ran. Machst Du das im Thread - wie oben - wird zwar der Thread von Delphi freigegeben, nicht aber die von SHFileOperation angelegten Objecte - nehme ich an. FastMM4! Aber auch das scheint nicht ganz so einfach.)

Warum soll ich immer das ganze Threadobject mitschleppen, wenn ich doch eigentlich nur das Handle brauche?
Allerdings bin ich momentan am Überlegen, ob eine TObjectList der Threads nicht vielleicht doch die bessere Lösung wäre.

Gruß
Mattze


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:49 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