Multithread Application
-
hallo,
pc man, ich hab so ein tut rumliegen, wenn du mir deine email gibst schick ichs dir...
murph
-
&junix:
Huch ist das so einfach?!?! Das wundert mich jetzt
Und ich habe tatsächlich eine Indy-Komponente drin laufen, irgendeine FTP-Indy-Komponente... da ich gerade nicht zuhause bin weiß ich nicht genau welche das ist.
Falls du auf TIDAntiFreeze anspielen willst, ich habe damit schon rumexperimentiert, aber bin zu keinem Resultat gekommen.&murph:
Danke, das wäre sehr nett: sende einfach an merkel@willkiffen.de
//Nein, die Mailadresse ist kein Fake
-
&junix: Ich habe mal deine Methode ausprobiert.
Ich bekomme nur nicht heraus, wie ich jetzt die TMyThread->Execute() zum Aufruf bringe! Kannst du mir da helfen?
-
Ich will mich ja nicht zu weit ausm Fenster lehnen aber ich bin mir ganz sicher das zum BCB (zumind. Versionen 4,5 u.6 die kenn ich) eine Beispielprogramm mit Thread dabei ist. Unter Examples und das lässt sich relativ leicht nachvllziehen, denn ich habs auch verstanden.
-
Tut mir leid, ich steige da kaum durch
-
Ich hab jetzt die Klasse FtpThread geschrieben, welche von TThread abgeleitet ist.
Funktionen:
Upload() der Upload auf den FTP und
Execute() die beinhaltet Synchronize(Upload)So, aber ich verstehe nicht, wie ich jetzt dies Execute zum rennen bekomme.
-
FtpThread = new FtpThread (true);//startet nicht gleich
//weitere Einstellungen
//durchfuehren
//Property einstellen ...
FtpThread ->Resume();//Ausfuehren (fortsetzen)PS: mit Upload in Synchronize wird das aber den Haupthread auch blockieren! ???
[ Dieser Beitrag wurde am 30.05.2003 um 19:39 Uhr von DerAltenburger editiert. ]
-
Nach ewigen Rumgetue und Rumgemache habe ich die Funktion Resume erst wahrgenommen.
&DerAltenburger:
Ich habe das Projekt vorsichtshalber nochmal kopiert, und mit dem anderen weiterexperimentiert. Es lief aber alles auf Anhieb gut, es waren nur kleine Korrekturen notwendig:TFtpThread *trst = new TFtpThread(true); trst=&TFtpThread(true);
Danke für die Hilfe, langsam verstehe ich auch was da vorsich geht.
[ Dieser Beitrag wurde am 30.05.2003 um 21:24 Uhr von PCMan editiert. ]
-
Ich hätte da allerdings noch eine Frage:
Ein char[1024] wird bei einem Thread von einer Funktion einen Wert zugewisen.
Das Problem ist nun, dass der Inhalt dieses Char-Arrays in Form1 gelesen werden muss. Ist zwar primitiv, aber ich habe die Variable dann einfach global definiert, was dazu führte, dass die Anwendung zwar startet, aber wenn ich nun den Thread starte, und danach aus einer Form1-Prozedur heraus versuche diese Variable auszulesen ist sie leer.
Woran kann das liegen?
-
bin ich so dumm???
-
Tschuldige, war ne Zeit offline.
Execute() solltst du nie direkt aufrufen, das besorgt der Thread bereits indem du Resume() aufrufst. (Siehe genauere Dokumentation in der VCL-Hilfe)
Zu deinem zweiten Problem... das hab ich irgendwie nicht ganz verstanden. Was ist genau das Problem?
-junix
-
&junix:
Okay, das mit Execute etc hab ich inzwischen verstanden und das mit dem Threads klappt ganz gut.
Jedoch gibt es da eine kleine Komplikation mit dem 2. Thread:
Im ihm wird eine DLL Funktion aufgerufen. Diese Funktion hat 3 Parameter: einen Int, einen Char und wieder einen Int. Die beiden Ints sind Parameter, die das Verhalten der Funktion im "Dll-Inneren" bestimmen, der Charparameter jedoch gibt nur einen Speicherort wieder. Das heißt, dass in diesem Char-Array (um genauer zu sein) eine Zeichenkette von der DLL Funktion abgespeichert wird.
Seitdem ich diesen DLL-Aufruf jetzt in einem eigenen Thread habe, wird dieses Char-Array allerdings nicht mehr beschrieben, es ist also leer.
Und ich weiß nicht woran das liegen könnte.
Danke
-
Zeig mal die Funktionsdeklaration und die Zeilen in denen du den String zuweist. Eventuell ist es auch ein Synchronisationsproblem. Schau dir mal in der Hilfe die Stichwörter TCriticalSection (wars glaub ich) an.
-junix
-
Danke, ich habe schon (ohne Erfolg jedoch) mit TCriticalSection gearbeitet.
Ich zeige dir mal den Code:/* unit1.h */ int Status; char fname[1024]; class TForm1 : public TForm { ... blablabla ... }; /* unit1.cpp bei OnButtonClick */ void __fastcall TForm1::BitBtn3Click(TObject *Sender) { ... //Der Thread ist in der Unit3.h definiert TReleaseShutterThread *trst = new TReleaseShutterThread(true); trst=&TReleaseShutterThread(true); trst->Priority=tpNormal; trst->Resume(); ... } /* unit3.h */ class TReleaseShutterThread : public TThread { private: protected: void __fastcall Execute(); public: void __fastcall Release(); __fastcall TReleaseShutterThread(bool CreateSuspended); }; /* unit3.cpp -> Dort findet der Aufruf statt! */ TDLLTest::TDLLTest() { HINSTANCE hInstance; hInstance = ::LoadLibrary("G2R.dll"); pDllFunction = (DLLFUNCTION*)::GetProcAddress((HMODULE)hInstance, "ReleaseShutter"); } int TDLLTest::CallDllFunction(int iTest1, const char* pFile, int iTest2) { int iResult; if (pDllFunction) iResult = (*pDllFunction)(60, fname, sizeof(fname)); return iResult; } void __fastcall TReleaseShutterThread::Release() { TDLLTest Dll; Status=Dll.CallDllFunction(60, fname,sizeof(fname)); } void __fastcall TReleaseShutterThread::Execute() { Synchronize(Release); }
Das DLL-Aufrufbeispiel entnahm ich der FAQ, funktionierte ganz gut.
So, wenn ich jetzt die Variablen int Status und char fname[1024] auslesen will, sind sie immer leer.
Danke junix[ Dieser Beitrag wurde am 01.06.2003 um 20:41 Uhr von PCMan editiert. ]
-
Den Code in der DLL hast du auch?
Verwende in der DLL mal ein TCriticalSection-Objekt welches du beim Eintritt in die Funktion mit Lock() blockierst und Unlock wieder löst beim Austritt aus der Funktion?
-junix
-
&junix:
Ja, das Problem ist eben, dass ich nur die DLL habe und nicht den Code darin.
Interessanterweise lief das alles problemlos, als das Einbinden der DLL und deren Aufruf sowie die Variablen alle noch in der unit1.h waren.
Also kann es nur an den Threads liegen.
Reicht es, wenn ich den Aufruf der DLL in eine CriticalSection packe? Vielleicht hab ich die CriticalSection nur falsch gesetzt?[ Dieser Beitrag wurde am 02.06.2003 um 12:54 Uhr von PCMan editiert. ]
-
Jo, doch das müsste reichen... Aber natürlich konsequent... hmm
Ich denk mal über dein problem nach... Rufst du die DLL-Funktion in verschiedenen Threads "gleichzeitig" auf?
-junix
-
&junix:
Negativ, dieser Thread mit dem DLL-Call wird nur einmal aus Unit1.cpp aufgerufen.
Wo genau müsste ich denn die CriticalSection hinpacken? Ich hab es einmal in unit1.cpp versucht, und zwar an der stelle:void __fastcall TForm1::BitBtn3Click(TObject *Sender) { ... //Der Thread ist in der Unit3.h definiert TCS->Aquire(); TReleaseShutterThread *trst = new TReleaseShutterThread(true); trst=&TReleaseShutterThread(true); trst->Priority=tpNormal; trst->Resume(); TCS->Release() ... }
Vielleicht ist die stelle falsch?
Oder die Umstände sind einfach so blöd, dass ich es hinnehmen muss, diesen Aufruf in der unit1.cpp zu lassen und damit ein kurzes Einfrieren zu riskieren
Danke nochmals, junix
-
Das war... ... voll der Zonk (o;
Du müsstest die Critical Section nur Locken bevor du die DLL-Funktion aufrufst und gleich anschliessend freigeben. Aber da du die DLL Funktion ehnur an einem Örtchen aufrufst, kannst du sie auch weglassen, dann ists kein Synchronisationsproblem... ...Was mach die DLL_Funktion denn? Irgendwelche WindowsMessages versenden?
-junix
-
&junix:
Die DLL kommuniziert mit einem Anderen Programm, dass im Background offen sein muss. Dieses Programm kann von dem PC aus den Auslöser einer Digitalkamera betätigen und das Bild fetchen.
Aber was die Funktion in der DLL genau macht weiß ich nicht, und wie die Kommunikation läuft weiß ich auch nicht.