watchdog
-
PAD schrieb:
Aber warum _endthread durch return erstzen??
Das _endthread würgt den Thread sofort und auf der Stelle ab. In Deinem Beispiel ist das auch kein Problem. Wenn nun aber Klassen dazukommen, werden keine Destruktoren aufgerufen. Und das finde ich bedenklich.
Wenn Du den Thread einfach auslaufen lässt, funktioniert das wieder. Intern wird dann sowieso _endthread aufgerufen. Ein direkter Aufruf ist überflüssig.
-
Danke für die Information, ist Gott sei Dank in meinem Sinne.
D.h. für die C-Fraktion ist es unerheblich ob sie return oder _endthread nimmt, für die C++ Fraktion ist es entscheidend das sie mit return arbeitet.
Da _endthread nicht mehr Leistung als return bietet, sollte man return in beiden Fraktionen nutzen
Sehe ich das richtig?
-
PAD schrieb:
Sehe ich das richtig?
Ja. Man kann sich aber auch in C ganz schnell 'ne Falle bauen:
void DoSomething(void* pv) { _endthread(); } void ThreadProc(void* pv) { void* pVoid = malloc(128); DoSomething(pVoid); free(pVoid); // hier kommst Du nie an return; }Also immer schön auf _endthread verzichten. Dann kann auch nichts passieren.

-
Schöne Sache, aber auch andere Statements als free werden genausoweinig ausgeführt.
Ein thread ist kein Funktionsaufruf sondern der Start eines eigenen Fadens - er kehrt nicht an die Stelle des Aufrufs zurück - , der beim Beenden auch noch ein paar lustige Sync probleme machen kann.void DoSomething(void* pv) { Sleep(2000); pPad[0]=300; _endthread(); } int* pPad; int main() { if (0==(pPad = malloc(128))) { printf("\nmalloc failed\n); return -1 } _beginthread(DoSomething(pVoid)); Sleep(500); free(pPad); // hier kommst du viel zu früh an return 0; }´tschuldigung natürlich muß DoSomething als thread aufgerufen werden.
-
Für mich sieht das gerade so aus, als ob du -King- nicht verstanden hast

DoSomething ist ja nicht die Thread-"Funktion", sondern eine Funktion, die aus den Thread (ThreadFunc) heraus aufgerufen wird.Du rufst ganz normal die Funktion DoSomething aus main auf und darin _endthread(); - was für einen Sinn soll das geben

-
flenders schrieb:
Du rufst ganz normal die Funktion DoSomething aus main auf und darin _endthread(); - was für einen Sinn soll das geben

Das hat natürlich keinen Sinn. Ich meine aber auch, daß das PAD bekannt ist. Man kann auch nicht einfach _beginthread auf einen Thread aufrufen, den man nicht gestartet hat.
Er wollte halt auf allgemeine Synchronisations-Probleme hinweiseisen, die es selbstverständlich auch gibt. Im Grunde ist das ein Beispiel für meine Behauptung, daß auch _beginthread verboten gehört. Aber als ich das zum letzten Mal losgeworden bin, wurde mir ans Herz gelegt, mich erstmal mit den Basics zu beschäftigen. Deswegen werde ich jetzt auch nicht näher darauf eingehen.
-
Entschuldigung für den Schreibfehler im Code, ich habe ihn korrigiert.
@ King Ohne die prügelen zu wollen, will soll man sonst in C multithreaded programmieren?
Ich brauche dazu eine Funktion des Betriebssystems, welche mir einen Thread startet.
-
PAD schrieb:
@ King Ohne die prügelen zu wollen, will soll man sonst in C multithreaded programmieren?
Jedenfalls nie mit _beginthread. Das Problem ist, daß Dich diese Funktion über die Geschehnisse im Unklaren lässt. Der Rückgabewert ist zwar das Thread-Handle, aber leider ist es nicht gültig (wird intern geschlossen). Verwendest Du stattdessen _beginthreadex, bekommst Du ein gültiges Handle geliefert. Damit kannst Du auch Deine Synchronisations-Probleme auf einen Schlag lösen. Allerdings mußt Du nun das Handle selbst schliessen. Das ist aber nun wirklich kein Problem. Ach ja, die Thread-Funktion hat auch eine andere Signatur. Du kannst jetzt sogar einen Wert zurückgeben!
UINT WINAPI DoSomething(void* pv) { Sleep(2000); pPad[0]=300; return(0); } int* pPad; int main() { HANDLE hThread; DWORD dwCode; if (0==(pPad = malloc(128))) { printf("\nmalloc failed\n); return -1 } hThread = (HANDLE)_beginthreadex(DoSomething(pVoid)); WaitForSingleObject(hThread, INFINITE); free(pPad); // hier kommst du an, wenn der Thread beendet ist if(WillHabenRückgabe) GetExitCodeThread(hThread, &dwCode); CloseHandle(hThread); // Thread-Handle zu Fuss schliessen return 0; }Ich brauche dazu eine Funktion des Betriebssystems, welche mir einen Thread startet.
Du sprichst von CreateThread? Das geht natürlich auch, nur mußt Du hier ganz genau wissen, was Du tust. Du übergehst damit die CRT. Solange Du im Thread nur API-Funktionen aufrufst, ist das auch kein Problem. Kommt eine Funktion aus der CRT ins Spiel, wird das schnell zum Abenteuer.
Schau Dir die allseits beliebte Funktion strtok an. Diese speichert Ihren Zustand bis zum nächsten Aufruf (der z.B. mit NULL im ersten Parameter erfolgen kann). Stell Dir jetzt zwei Threads vor, die gleichzeitig strtok verwenden möchten.
Probleme machen auch alle die Funktionen, die Fehler melden. Der VC löst das beispielsweise über errno. Aber welchen Fehler hält die Variable? Zu welcher Funktion aus welchem Thread gehört das?
Wenn Du aber die CRT Funktion _beginthread/ ex verwendest, gibt es all diese Probleme nicht. Über die interne Initialisierung ist es möglich, daß jeder Thread seinen eigenen Zustand halten kann.
-
@-King- Danke für die Information über die Probleme von _beginthread.
Mit dem Überlappen habe ich keine Probleme, ich wollte nur zu deinem Beispiel des nicht erreichbaren free´s noch ein anderes typisches Problem von multithreading zeigen.
Die Lösung vor dem Verlassen des Hauptprogramms auf alle threads zu warten, kann auch nicht das Designproblem beheben das der thread einer inzwischen freigegebenen Variablen einen Wert zuweist.
Eigentlich war deine Antwort mit _beginthreadex schon ausreichend, denn wenn du _beginthread ablehnst (mit sinnvollen Gründen) braucht man eine Alternative dazu, das diese schon durch _beginthreadex gegeben ist, war aus deinem Text nicht ersichtlich.
-
hab die folgenden header includiert
#include <windows.h>
#include <process.h>
#include <iostream.h>und er mag das einfach ned machen:
itsThreadHandle = (HANDLE) _beginthreadex(inputfunktion());
und spuckt das aus:
Borland C++ 5.6 für Win32 Copyright (c) 1993, 2002 Borland
threads.cpp:
Fehler E2268 threads.cpp 24: Aufruf der undefinierten Funktion '_beginthreadex'
in Funktion MyThread::startThread()
*** 1 Fehler bei der Compilierung ***was bringt das UINT WINAPI vor DoSomething(void* pv) eigentlich?
was hat beginthreadex noch so für parameter (MSDN bringst mir nix)?Gruß TheChosn
-
TheChosn schrieb:
Borland C++ 5.6 für Win32 Copyright (c) 1993, 2002 Borland
threads.cpp:
Fehler E2268 threads.cpp 24: Aufruf der undefinierten Funktion '_beginthreadex'
in Funktion MyThread::startThread()
*** 1 Fehler bei der Compilierung ***Ich könnte mir vorstellen, dass die Funktion im BCB anders heißt

TheChosn schrieb:
was bringt das UINT WINAPI vor DoSomething(void* pv) eigentlich?
afaik ist UINT der Rückgabetyp und WINAPI (define aus windef.h) die Aufrufkonvention ( __cdecl )
TheChosn schrieb:
was hat beginthreadex noch so für parameter (MSDN bringst mir nix)?
Wie hast du denn gesucht? http://msdn.microsoft.com/library/en-us/vccore98/html/_crt__beginthread.2c_._beginthreadex.asp
-
Hmm konnte nix finden was borland spezifisch wäre, das is in der header datei von borland.
unsigned long _RTLENTRY _EXPFUNC _beginthreadex(void *__security_attr,
unsigned __stksize,
unsigned (__stdcall *__start)(void *),
void *__arg,
unsigned __create_flags,
unsigned *__thread_id);Kannst du mir bitte noch kurz erklären was es mit den calling conventions auf sich hat?
The routine at start_address must use the __cdecl calling convention and should have no return value.
Wie finde ich die adresse einer Funktion raus, mag sie im konstruktor übergeben gehört ned der klasse.
Gruß TheChosn
-
das mit den calling conventions bestimmt afaik, in welcher Reihenfolge die Parameter an die Funktion übergeben werden (von rechts nach links, oder umgekehrt)

Du musst immho einfach den Namen übergeben (so wie z.B. bei Fensterklassen - WndProc)
-
Hast du dem Borland Compiler auch mitgeteilt, das du multithreaded arbeiten willst. Ich kann mich erinnern das wir eine ähnliche Fehlermeldung hatten als wir einmal unter MSVC 6.0 als wir in einer als singlethreraded definierten Applikation einen thread aufmachen wollten.
-
Wie kann ich meinem Borland Compiler denn das mitteilen?
Bin leider ziemlicher Anfänger
Gruß TheChosn
-
flenders schrieb:
afaik ist UINT der Rückgabetyp und WINAPI (define aus windef.h) die Aufrufkonvention ( __cdecl )
WINAPI ist __stdcall.
flenders schrieb:
das mit den calling conventions bestimmt afaik, in welcher Reihenfolge die Parameter an die Funktion übergeben werden (von rechts nach links, oder umgekehrt)
Das ist richtig, aber nur die halbe Wahrheit. Zusätzlich wird festgelegt, wer den Stack aufräumt (die Funktion oder der Aufrufer).
-
Was ist jetz eigentlich der unterschied zwischen den beiden
außer Security, Init & Adressflag?
Liefern die nicht beide ein handle?_beginthread
_beginthreadexHab immer noch keinen Erfolg mit der Compilierung, hat es sinn sich im Cbuilder Forum umzuhören oder verwendet niemand mehr den ollen commadozeilen compiler?
-
<a href= schrieb:
http://msdn.microsoft.com/library/en-us/vccore98/html/_crt__beginthread.2c_._beginthreadex.asp">_beginthreadex resembles the Win32 CreateThread API more closely than does _beginthread. _beginthreadex differs from _beginthread in the following ways:
- _beginthreadex has three additional parameters: initflag, security, threadaddr. The new thread can be created in a suspended state, with a specified security (Windows NT only), and can be accessed using thrdaddr, which is the thread identifier.
- The routine at start_address passed to _beginthreadex must use the __stdcall calling convention and must return a thread exit code.
- _beginthreadex returns 0 on failure, rather than 1.
- A thread created with _beginthreadex is terminated by a call to _endthreadex.
-
Wie sieht dein Code jetzt eigentlich aus? Falls du Probleme mit deinem Compiler hast findest du sicher im BCB (oder andere Compiler?) Forum jemanden, der dir helfen kann

-
TheChosn schrieb:
Liefern die nicht beide ein handle?
Ja, liefern sie. Das HANDLE von _beginthread ist aber leider schon geschlossen. Damit kannst Du weiter nichts beschicken. Du kannst lediglich feststellen, ob der Aufruf geklappt hat oder nicht.