Forum: PC-Programmierung WinAPI und Threads


von Thomas M. (Gast)


Angehängte Dateien:

Lesenswert?

Hi,

ich erzeuge mein Thread in WinAPI und VC so:

hThread = CreateThread(
      NULL,
                  0,
      ThreadFunc,
      &dwThrdParam,
      0,
      &dwThreadId);identifier

SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);

und beende es so:

void TermThread()
{
     GetExitCodeThread(hThread, lpExitCode);
  ExitThread(*lpExitCode); // Diese Zeile verursacht Fehler
  CloseHandle(hThread);
}

Wie schon in der Zeile kommentiert, verursacht diese Zeile einen Fehler
- siehe Anhang!

Dass der Thread erzeugt wir, weiss ich da die Routine funktioniert aber
warum lässt sich der Thread nicht schliessen?

Was muss man da beachten, eigentlich ist das nichts wildes.

von Rufus T. Firefly (Gast)


Lesenswert?

Ist denn lpExitCode möglicherweise NULL?

Wer ruft Deine Funktion TermThread auf? Die Threadroutine oder etwa der
Hauptthread? (Der darf das nicht und würde sich selbst damit
terminieren)

von Hans (Gast)


Lesenswert?

hmm könntest du mal deine threadfunc posten ???

dir ist schon klar,dass exitthread aus dem thread der beendet werden
soll aufgerufen wird oder??? btw TerminateThread hat etwas ganz
lustiges in der doku stehn.... (TerminateThread is a dangerous function
that should only be used in the most extreme cases. ) also das ist eine
subtil bösartige funktion ;)

und dann wäre noch das..


     GetExitCodeThread(hThread, lpExitCode);
  ExitThread(*lpExitCode); // Diese Zeile verursacht Fehler

hier müsste lpExitCode mit einem DWORD *lpExitCode=new DWORD oder
ähnlichen initialisiert werden... und dann muss noch mit delete der
speicher wieder freigegeben werden...

ich finde da sowas irgendwie praktischer...
DWORD dwExitCode;
GetExitCodeThread(hThread, &dwExitCode);
ExitThread(dwExitCode);

ich schätze die access-violation kommt vom dereferenzieren vom pointer
lpExitCode der aber nicht richtig initialisiert ist...

73 de oe6jwf / hans

von Thomas M. (Gast)


Lesenswert?

Das sit meine Threadfunktion:

DWORD WINAPI ThreadFunc( LPVOID *lpParam )
{
  while(TRUE)
  {
    USARTRec();
    Sleep(1);
  }
  return 0;
}

dir ist schon klar,dass exitthread aus dem thread der beendet werden
soll aufgerufen wird oder???

Nein, das war mir nicht klar. Es geht nur darum, dass wenn nichts
empfangen wird, der Thread geschlossen werden kann und das wir an eine
anderen Stelle überprüft.

von Rufus T. Firefly (Gast)


Lesenswert?

Das Terminieren des Threads lässt sich so realisieren:

Statt in der Threadfunktion ein Sleep(1) aufzurufen, wird mit
WaitForSingleObject() auf ein Eventhandle gewartet.

  if (WaitForSingleObject(hEvent, 1) == WAIT_TIMEOUT)
    // weitermachen
  else
    // aufhören

Dieses Event wird mit CreateEvent erzeugt:

   hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

Das Eventhandle kann der Threadfunktion beispielsweise über den opaken
Pointer lpParam übergeben werden (sofern der nicht schon anderweitig
genutzt wird).

Das Event kann von beliebigen Threads mit SetEvent ausgelöst werden:

   SetEvent(hEvent);

Anzumerken ist noch, daß ein Sleep(1) nicht sehr sinnvoll ist, da die
Schedulergranularität bei 10 msec liegt - es sei denn, sie ist mit
timeBeginPeriod reduziert worden.

Um beim Beenden des Threads sicherzugehen, daß der sich auch wirklich
beendet, kann nach den Setzen des Events mit WaitForSingleObject auf
das Threadhandle gewartet werden - das nämlich wird bei Beendigung des
Threads signalisiert.

Eine Auswertung des ThreadExit-Codes oder gar ein Aufruf von ExitThread
ist so nicht erforderlich. ExitThread wird durch return aus der
Threadfunktion eh' impizit aufgerufen.

von Hans (Gast)


Lesenswert?

oder CEvent der mfc verwenden.. geht auch ganz fein...

73 de oe6jwf/hans

von Rufus T. Firefly (Gast)


Lesenswert?

... wenn man denn MFC verwendet.
Dann aber würde es sich auch empfehlen, eine der Kapselungsklassen für
Threads zu verwenden (CWinThread o.ä.).

Sinnvoll ist es aber meiner Ansicht nach, zunächst einmal die
Mechanismen des OS zu begreifen, bevor man sie mit einer
Klassenbibliothek verbirgt.

von Chris (Gast)


Lesenswert?

CreateThread sollte man übrigens niemals benutzen, außer man ist sich
allen Einschränkungen genauestens bewusst (was bei dir mit Sicherheit
nicht der Fall ist).

Nimm z.B. die Funktion strstr, die einen statischen Puffer besitzt. Von
CreateThread bekommt strstr nichts mit. Also haben beide Threads
denselben Puffer, wodurch schnell extrem schwer zu findende Fehler
entstehen (die fieserweise im Debugger gar nicht auftauchen).

Schau in die Doku deines Compilers. Die Lib des Compilers bietet
garantiert eine Funktion _beginthread, _beginthreadex, beginthread o.ä.
an. Nur diese Funktion ist geeignet, in C einen Thread zu erstellen;
denn nur mit dieser Funktion bekommt die C-Standard-Lib etwas mit von
der Threaderstellung und kann statische Variablen für den neuen Thread
initialisieren.
CreateThread ist böse.

Die Threadfunktion sollte außerdem einfach "auslaufen", d.h. mit
return aufhören. Denn nur dann hat die C-Standard-Lib eine Chance, den
für den Thread reservierten Speicher wieder freizugeben. ExitThread,
TerminateThread etc. sind verboten.

von Thomas M. (Gast)


Lesenswert?

In der MSDN Library
:http://msdn.microsoft.com/library/deu/default.asp?url=/library/DEU/
vccore/html/_core_C_Run.2d.Time_Library_Functions_for_Thread_Control.asp

steht aber, dass CreateThread für Win32 API gedacht ist?

von Chris (Gast)


Lesenswert?

_beginthread ruft intern natürlich auch CreateThread auf. Nur vorher
wird halt noch die C-Standard-Lib für den neuen Thread initialisiert.

CreateThread funktioniert zwar, du darfst dann allerdings die
Funktionen der C-Standard-Bibliothek nicht benutzen; genau diese
Warnung steht auch auf der von dir verlinkten Seite.


p.s.: Solche langen URLs bitte über tinyurl.com posten, damit sie nicht
umgebrochen werden.

von nobody0 (Gast)


Lesenswert?

Kann man unter MS-Windows denn keine Posix-Threads nehmen?
Das CreateThread ist doch kein bischen portabel und vielleicht gibt's
das beim nächsten MS-Windows nicht mehr, während pthread_create
sicherlich auch in 100 Jahren noch unter so ziemlich jedem
Posix-konformen Betriebssystem funktionieren wird.

von Rufus T. Firefly (Gast)


Lesenswert?

Früher gab es standardmäßig eine Posix-kompatible Umgebung für Windows
(als paralleles Subsystem), die aber ist wohl aufgrund von
Nichtbeachtung seitens der Anwendungsprogrammierer gestorben.
Von MS gibt es allerdings ein größeres Paket, das sich wohl "UNIX
Services for Windows" oder so ähnlich nennt, das POSIX-Kompatibilität
und einiges weiteres nachrüstet.


CreateThread selbst ist ausgesprochen langzeitstabil - an der Funktion
und ihrem Gebrauch hat sich seit Herbst 1992 nichts wesentliches
geändert. Damals gab's die erste verfügbare Beta-Version von NT 3.1,
und mit der habe ich zu der Zeit bereits gearbeitet.

Wesentlich hat sich eigentlich nur die Dokumentation geändert - die ist
seitdem viel besser geworden. Musste man damals bei den meisten
Parametern oder auch kompletten Systemfunktionen raten, wofür sie da
sein mögen, sind mittlerweile auch recht kleine Details dokumentiert.

Posix-Threads begegnete ich etwas später erstmalig unter Lynx-OS, einem
unixoiden Echtzeitbetriebssystem. Die frühen Linux-Varianten der Zeit
unterstützten meines Wissens nach noch keine Posix-Threads; ich will
allerdings nicht ausschließen, daß ich mich da irre.

von nobody0 (Gast)


Lesenswert?

Das mit der posix-kompatiblen Umgebung für Windows ist aber mehr ein
Gerücht als Realität, denn zu Posix gehört nach Tanenbaum
beispielsweise Fork und eine Shell, die ls versteht.
Nur weil Microsoft ein, zwei Posix-Funktionen gemacht hat, ist das noch
längst keine Posix-Umgebung.

von Tobi (Gast)


Lesenswert?

"...und eine Shell, die ls versteht."
man windows kann von natur aus schon ls und andere befehle aus der
unix/linux welt

von Thomas X. (Gast)


Lesenswert?

> Kann man unter MS-Windows denn keine Posix-Threads nehmen?

sowas fragt man am besten google:

http://www.google.ch/search?hl=de&q=pthread+win32&meta=

und dann kommt zum beispiel das dabei raus:

http://sources.redhat.com/pthreads-win32/

hab das jetzt nicht näher angeschaut...ich brauch ja keine pthreads :D

von Matthias (Gast)


Lesenswert?

Hi

@Tobi
Hast du WinAVR installiert?
AFAIK kann ein naturnahes Windows kein ls in der Befehlszeile. WinAVR
rüstet diese Tools nach. Aber eigentlich will man sowieso eine
Cygwin-Umgebung auf einem ordentlichen Windows haben. Eine Bash ist
IMHO unverzichtbar.

Matthias

von nobody0 (Gast)


Lesenswert?

Ja, das sehe ich auch so, denn a) gibt es unter MS-Win nur
Posix-ähnliche Befehle wie dir statt ls und b) entsprechen die den
Posix-Befehlen nur ein bischen. Ansonsten würden Shell-Skripte auch
unter MS-Win funktionieren und man bräuchte kein cygwin.
Weil Microsoft ständing die Programmierschnittstellen ändert, so dass
beispielsweise meine alten Turbo-Pascal-Programme nicht mehr laufen
(selbst wenn der runtime division by zero bug beseitigt ist), achte ich
auf Portabilität und verwende mölichst nur Standard-Sachen, also
ANSI/ISO-C, Posix usw..

von Rufus T. Firefly (Gast)


Lesenswert?

"Weil Microsoft ständing die Programmierschnittstellen ändert" - was
exakt magst Du da jetzt meinen?

Die Einführung der Win32-API vor bald zwölf Jahren? Das damit
eingeleitete Ende von DOS?

Posix-Konformität muss mitnichten die Shell einschließen. Die
Posix-Konformität besteht aus einer Reihe von Punkten, die
beispielsweise hier
http://www.microsoft.com/resources/documentation/windowsnt/4/workstation/reskit/en-us/poscomp.mspx
beschreiben sind.
Das NT*-eigene Posix-Subystem enspricht Posix.1

Mittlerweile wird dieses Posix-Subsystem durch ein Produkt namens
Interix bzw. "Windows Services for Unix" ersetzt, das man sich wohl
kostenfrei herunterladen kann
http://www.microsoft.com/windows/sfu/default.asp



*) NT schließt auch Windows 2000, XP und Windows 2003 ein, allerdings
fehlt das Posix-Subsystem bei Windows XP

von Rufus T. Firefly (Gast)


Lesenswert?

Noch was:
Hier wird die Unterstützung von PThreads beschrieben
http://www.microsoft.com/technet/interopmigration/unix/sfu/pthreads0.mspx

von nobody0 (Gast)


Lesenswert?

@ Rufus T. Firefly:
Unter Posix verstehen Informatiker eine Umgebung, wie sie z. B.
Tanenbaum im Buch "Moderne Betriebssysteme beschreibt"; dazu gehört
neben Fork und Pthreads auch eine Shell, die ls versteht. Schließlich
gibt's viele einzelne Posix-Standards.
Und da dem MS-WinXP das Posix-Subsystem fehlt, ist es sehr weit weg von
Posix.

von Rufus T. Firefly (Gast)


Lesenswert?

"Unter Posix verstehen Informatiker ..."
Siehst Du hier irgendwo Informatiker?

von T.Stütz (Gast)


Lesenswert?

@Rufus T. Firefly
Ja, wenn ich in den Spiegel schaue dann "sehe" ich einen...
grins
zum Thema:
mal egal ob man XP als POSIX-Kompatibel oder nicht bezeichnet in der
heutigen Zeit ist es vielleicht besser sich zu überlegen was man machen
will, anstatt einem (alten) "Standart" hinterherzuhinken.

zum anderen nützt es nix wenn mann dann zwar "unix"/Posix kompatibel
programmieren/zugreifen kann, die zugrundeliegende API (Windoof) per se
schon unsicher ist - oder glaubt hier irgendjemand das XP "sicher" ist
?

Gruss

von Rufus T. Firefly (Gast)


Lesenswert?

Ich mag diese relgiös-fundamentalistischen Diskussionen nicht.

Die eigentliche Frage, wie man Threads unter Windows erzeugt, wurde
geklärt, auf potentielle Probleme wurde hingewiesen und Alternativen
wurden auch erwähnt.

Hier jetzt das übliche Geseiere "unix/linux ist vieeel besser" bzw.
"XP ist aber cooler" abzulassen ist nicht förderlich.


Was ist ein "Standart"?
Ich kenne nur Standart: aufrecht, leicht vornübergebeugt, lässig ...

Stehen ist statisch und nicht mit Hinken in Einklang zu bringen.

Alternativen zum Gebrauch der Win32-Thread-Funktionen:
- PThreads (mit SFU3.5)
- Threadwrapper einer Klassenbibliothek (MFC, wxWidgets, Qt)
- Auf Threads verzichten, um sich persönlich nicht zu überfordern

von Thomas X. (Gast)


Lesenswert?

> Auf Threads verzichten, um sich persönlich nicht zu überfordern

richtig. es geht häufig auch ohne, mit weniger kopfzerbrechen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.