Multithread Application
-
Hallo
Folgendes Problem: Ein Programm lädt ein Bild auf einen FTP Server hoch.
Das Problem ist, dass wärend das Programm hochlädt es sozusagen "einfriert", also unbedienbar.
Sowas würde ich gerne vermeiden. Im IRC sagte man mir, mann müsste dazu einen neuen Thread schreiben. Ich hab mich jetzt ein bisschen umgesehen (BCB Hilfe) sowie in der FAQ, aber ich verstehe immer noch nicht, wie ich jetzt soetwas aufziehe.
Bin auch für Tutorials sehr dankbar.
PCMan
-
Es weiß wirklich niemand, wie man einen neuen Thread aufzieht?
*push*
-
Was du brauchst ist ein TThread-Objekt (Datei->Neu->Thread)
-junix
-
Btw. Benutzt du Indy-Kompos?
-junix
-
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