Autor |
Beitrag |
tif
      
Beiträge: 46
Erhaltene Danke: 1
Winxxx
TP, BP, Delphi 1 - 2009
|
Verfasst: Fr 05.03.10 09:23
Hallo,
ich erzeuge in meiner Anwendung mehrere Threads, die ihrerseits ein Datenmodul beinhalten. In diesem Datenmodul erfolgt eine u.U. längerdauernde Verarbeitung.
Nun möchte ich von der Hauptapplikation aus bei Bedarf diese Verarbeitung(en) abbrechen. Damit das sauber im Datenmodul gehandlet wird, wollte ich nicht die Threads in einer Liste führen und dann per Terminate einzeln abschießen, sondern lieber dem Datenmodul freundlich mitteilen, dass es die Verarbeitung beenden soll.
Dazu möchte ich an alle Datenmodule einer bestimmten Klasse eine - nennen wir sie mal WM_CANCEL - Botschaft schicken.
Ich bekomme es aber nicht hin und frage deshalb hier um Rat.
Das habe ich:
Im Datenmodul
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43:
| Tdm_window = class(TDataModule) procedure DataModuleCreate(Sender: TObject); procedure DataModuleDestroy(Sender: TObject); private handle:hwnd;
procedure CreateCommunicationWindow; procedure CM_Cancel(var Msg:TMessage); message WM_CANCEL; procedure DestroyCommunicationWindow;
public end;
implementation
procedure Tdm_window.CreateCommunicationWindow; var adr:Pointer; begin handle := CreateWindowEx(0, 'STATIC', PChar(name), 0, 0, 0, 0, 0, 0, 0, hinstance, nil); adr:=MakeObjectInstance(CM_Cancel); SetWindowLong(handle, GWL_WNDPROC, LongInt(adr)); end;
procedure Tdm_window.DestroyCommunicationWindow; begin destroywindow(handle); end;
procedure Tdm_window.DataModuleCreate(Sender: TObject); begin CreateCommunicationWindow; end;
procedure Tdm_window.DataModuleDestroy(Sender: TObject); begin DestroyCommunicationWindow; end; procedure Tdm_window.CM_Cancel(var Msg: TMessage); begin showmessage('Abbruch'); end; |
Und der Aufruf
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| procedure TForm2.btn_1Click(Sender: TObject); var hwnd:Integer; begin HWND:=FindWindowEx(Application.Handle,0,'dm_window',''); PostMessage(HWND,WM_CANCEL,0,0); end; |
Ich habe schon mit FindWindow / FindWindowEx alle möglichen Variationen durchprobiert, aber keine 'trifft' das Datenmodul.
Habt Ihr einen Lösungsansatz?
Danke
Tino Moderiert von Narses: Topic aus Sonstiges (Delphi) verschoben am Fr 05.03.2010 um 11:07
|
|
Xion
      

Beiträge: 1952
Erhaltene Danke: 128
Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
|
Verfasst: Mo 15.03.10 11:13
tif hat folgendes geschrieben : |
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| procedure TForm2.btn_1Click(Sender: TObject); var hwnd:Integer; begin HWND:=FindWindowEx(Application.Handle,0,'dm_window',''); PostMessage(HWND,WM_CANCEL,0,0); end; | |
Probiers mal mit Tdm_window. Du musst dann aber in dem Stück, wo die arbeit gemacht wird, mit Application.ProcessMessages prüfen, ob messages da sind, das bremst die Arbeit durchaus, du kannst natürlich nur jede Sekunde prüfen, dann braucht das Programm ne Sekunde zum abbrechen, wäre wohl der beste Kompromiss.
Warum machst du nicht einfach ein array, wo du die Dinger rein"constructest":
Delphi-Quelltext 1:
| DataModules[0]:=Tdm_Window.DataModuleCreate(...); |
Den DataModuleCreate dann als Constructor deklarieren.
Dann kannst du einfach mit DataModules[0].CM_Cancel das gleiche erreichen wie so über die messages. (Oder nicht?  )
_________________ a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)
|
|
tif 
      
Beiträge: 46
Erhaltene Danke: 1
Winxxx
TP, BP, Delphi 1 - 2009
|
Verfasst: Mo 15.03.10 11:56
Hallo,
vielen Dank für die Antwort!
Ja, dass bei FindWindow der Klassenname stehen muss, das hab' ich dann auch gemerkt, trotzdem danke für den Hinweis.
Trotzdem findet er das Fenster nicht - und schon gar nicht 'alle aktiven', wenn es mehrere Treads gibt.
Irgendwie kam ich mit FindWindow / FindWindowEX nicht weiter.
Ich habe es dann doch - wie vorgeschlagen - über eine globale Thread - Liste gemacht, war gar nicht so schlimm wie ich erst vermutet hatte:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41:
| interface
ThreadList : TThreadList; Function ClearThreads : Boolean;
implementation
Function ClearThreads : Boolean; var al: TList; i,cnt : Integer; begin cnt:=0;
while cnt < 10 do begin al:=ThreadList.LockList; try if al.Count = 0 then begin cnt:=11; Result:=True; end else begin Inc(cnt); for i := 0 to al.Count - 1 do if Assigned(al[i]) then TThread(al[i]).Terminate; end; finally ThreadList.UnlockList; end; if cnt < 11 then Sleep(1000); end;
end;
Initialization ThreadList:=TThreadList.Create; finalization ClearThreads; ThreadList.Free; end. |
Und im Thread / Datenmodul:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| type TExportThread = class(TThread) private protected
procedure Execute; override; public constructor Create(Params:TExportParams); virtual; destructor Destroy; override; end;
Implementation
constructor TExportThread.Create(Params: TExportParams); begin
FreeOnTerminate:=True; with ThreadList.LockList do try add(self); finally ThreadList.UnlockList; end;
inherited Create(false); end;
destructor TExportThread.destroy; begin
with ThreadList.LockList do try remove(self); finally ThreadList.UnlockList; end;
inherited; end; |
Schließlich bei der Verarbeitung im Thread terminated abfragen, wenn true -> Abruch
Also, Danke, viele Grüße und sorry, dass ich dies nicht schon längst gepostet habe!
Ich war ein wenig traurig, weil solang keine Reaktion erfolgt ist.
Tino
|
|
HelgeLange
      
Beiträge: 735
Erhaltene Danke: 6
Windows 7
Delphi7 - Delphi XE
|
Verfasst: Mo 15.03.10 15:24
wenn ich mich recht entsinne, haben zwar TForm und TDataModule gemeinsame Vorfahren, aber den Datenmodule fehlt wohl das Fensterhandle, da es ein unsichtbares Container-Module ist. Wahrscheinlich kriegt es nur im design-Mode ein Handle zugewiesen, damit man Komponenten reinlegen kann.
Hab leider aber gerade keine Zeit, da im Forms-code rumzusuchen.
_________________ "Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
|
|
tif 
      
Beiträge: 46
Erhaltene Danke: 1
Winxxx
TP, BP, Delphi 1 - 2009
|
Verfasst: Mo 15.03.10 15:37
Ja, das ist ein Teil ursprünglichen Problems.
Genau das soll das CreateCommunicationsWindow() aus meinem ersten Post für's Datenmodul 'nachrüsten'.
Der Code stammt sinngemäß aus der (VCL) Forms.pas.
Es wäre interessant zu wissen, ob das so richtig ist oder ob bereits hier der Fehler liegt, dass das Fenster per Findindow() nicht zu finden ist.
Danke
Tino
|
|
HelgeLange
      
Beiträge: 735
Erhaltene Danke: 6
Windows 7
Delphi7 - Delphi XE
|
Verfasst: Di 16.03.10 16:00
Dann nimm doch einfach ein Formular, statt eines Datenmodules. Das ist ja der unterschied. Oder richte Dir ein kleines fenster ein, hab leider keinen Beispiel code zur Hand, da ich meinen "richtigen" Delphi-Rechner noch in Caracas hab, ich aber jetzt in Kolumbien wohne... Falls Du bis ende April Zeit hast, kann ich dann ja mal schaun...
Ich weiss, dass ich es früher mal so gemacht hatte und es ging gut.
_________________ "Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
|
|
tif 
      
Beiträge: 46
Erhaltene Danke: 1
Winxxx
TP, BP, Delphi 1 - 2009
|
Verfasst: Di 16.03.10 16:32
Hallo,
danke für deine Antwort!
Bitte mach dir erstmal keine Mühe mehr, ich hab's inzwischen über eine Liste gelöst.
Ich möchte kein Formular verwenden, da diese Anwendung später auch als Dienst laufen soll - und ich damit die unit Forms nicht einbinden darf.
Wahrscheinlich ist bei mir aber schon das Konzept falsch: An einen Dienst Windows- Fensterbotschaften schicken zu wollen ist eventuell widersinnig.
Abgesehen davon, dass ich HIER eine Lösung habe, wäre es natürlich interessant, wie man ein unsichtbares Fenster erzeugt, findet und dann auch benachrichtigt.
Hier gibt es aber im www viele Beispiele, die ich erstmal anschauen muss. Dann gibt's ggf. noch konkretere Fragen.
Also, Danke und viele Grüße nach Übersee!
Tino
|
|
HelgeLange
      
Beiträge: 735
Erhaltene Danke: 6
Windows 7
Delphi7 - Delphi XE
|
Verfasst: Mi 17.03.10 15:50
Schau mal bei den ICS Komponenten (sind kostenlos und mit vollem Source), dort hab ich mal gesehen, dass die sich ein Fenster erzeugen, um sich selbst Nachrichten zu senden wegen irgendwelchen asynchronen Sachen.
_________________ "Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
|
|
|