Was ist an KillThread() so "gefährliche"

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Was ist an KillThread() so "gefährliche"

Beitrag von STARGÅTE »

Tachchen,

ist n etwas dumme frage, aber in der Hilfe steht :
Zerstört den angegebenen Thread, der zuvor mit CreateThread() erstellt wurde. Dies ist eine sehr gefährliche Operation, benutzen Sie sie sofern möglich nicht.
Und da ich zur Zeit zimlich viele KillThread() benutze und es wirklich bei 10% der Programmausführungen zum Absturtz kommt, wollte ich wissen ok dieses KillThread ein auslöser sein kann.
Ist es denn wirklich so das KillThread den Thread sofort killt ?, egal wo, und was gerade im Thread passiert?, oder ist das Ding schon etwas schlauer und KillThread wartet ab bis der "angefangene" Byte zuende gelesen wurde?


Als Zusatzfrage hätte ich noch gerne gewusst wie "sicher" dise API hier ist :

Code: Alles auswählen

EnterCriticalSection_(@Mutex)
LeaveCriticalSection_(@Mutex)
denn schließlich muss doch dort auch mindestens ein BYTE geändert werden und das könnte doch auch wieder eine Fehlerquelle bei Theads sein oder ?
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
freak
PureBasic Team
Beiträge: 766
Registriert: 29.08.2004 00:20
Wohnort: Stuttgart

Beitrag von freak »

MS Platform SDK hat geschrieben:TerminateThread is used to cause a thread to exit. When this occurs, the target thread has no chance to execute any user-mode code and its initial stack is not deallocated. DLLs attached to the thread are not notified that the thread is terminating.

TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:
  • If the target thread owns a critical section, the critical section will not be released.
  • If the target thread is allocating memory from the heap, the heap lock will not be released.
  • If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.
  • If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.
Benutzeravatar
mk-soft
Beiträge: 3845
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag von mk-soft »

Thread zum Beispiel über Globale Variable erst beenden.

Code: Alles auswählen

;- Konstanten
Enumeration ; Window ID
  #Window
EndEnumeration

Enumeration ; Menu ID
  #Menu
EndEnumeration

Enumeration ; MenuItem ID
  #Menu_Stop
  #Menu_Exit
EndEnumeration

Enumeration ; Statusbar ID
  #Statusbar
EndEnumeration

Enumeration ; Gadget ID
  #List
EndEnumeration

; ***************************************************************************************

;- Globale Variablen
Global exit = 0

; ***************************************************************************************

Procedure UpdateWindow()

  Protected x,y,dx,dy
  Protected mn,st,tb
  
  x = 0
  y = 0
  mn = MenuHeight()
  st = StatusBarHeight(#StatusBar)
  ;tb = ToolBarHeight(#ToolBar)
  dx = WindowWidth(#Window)
  dy = WindowHeight(#Window) - mn - st - tb
  ResizeGadget(#List, x, y, dx, dy)
  
EndProcedure

; ***************************************************************************************

Global MyThread.l
Global MyThreadStop.l = #False

Procedure MyThread(ID)

  AddGadgetItem(#List, -1, "Startup...")
  Delay(2000)
  AddGadgetItem(#List, -1, "Running...")
  
  While Not MyThreadStop
    Delay(1000)
    AddGadgetItem(#List, -1, FormatDate("Working: %hh:%ii:%ss", Date()))
  Wend
  
  AddGadgetItem(#List, -1, "Stopping...")
  Delay(2000)
  AddGadgetItem(#List, -1, "Stopped.")
  
EndProcedure

;- Fenster
style = #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget
If OpenWindow(#Window, #PB_Ignore, #PB_Ignore, 400, 300, "Fenster", style)
  ; Menu
  If CreateMenu(#Menu, WindowID(#Window))
    MenuTitle("&Datei")
      MenuItem(#Menu_Stop, "&Stop Thread")
      MenuItem(#Menu_Exit, "Be&enden")
  EndIf
  ; Statusbar
  CreateStatusBar(#Statusbar, WindowID(#Window))
  ; Gadgets
  If CreateGadgetList(WindowID(#Window))
    ListViewGadget(#List, 0,0,0,0)
  EndIf
  
  MyThread = CreateThread(@MyThread(), 0)
  
  ;-- Hauptschleife
  Repeat
    event   = WaitWindowEvent(100)
    window  = EventWindow()
    menu    = EventMenu()
    type    = EventType()
    Select event
      Case #PB_Event_Menu
        Select menu
          Case #Menu_Exit
            Exit = 1
          Case #Menu_Stop
            MyThreadStop = #True
            
        EndSelect
      Case #PB_Event_Gadget
      Case #PB_Event_CloseWindow
        Exit = 1
      Case #PB_Event_Repaint
      Case #PB_Event_SizeWindow
        UpdateWindow()
        
      Case #PB_Event_MoveWindow
      Case #PB_Event_ActivateWindow
      Case #PB_Event_SysTray
    
    EndSelect
    
    If Exit
      If IsThread(MyThread)
        Exit = 0
        MessageRequester("Info", "Thread läuft noch. Erst Thread stoppen")
      EndIf
    EndIf     
    
  Until Exit
EndIf
FF :wink:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

nette idee aber:

1. die Globale Variable [MyThreadStop] ist in dem CODE ungesichert.
also würde dies auch in Ausnahmefällen zum absturtz führen.

2. Ich würde ja gerne den Thread mit einer "Info" beenden lassen, aber dieser Thread hat so hohe warte Zeiten in sich drin (2s-5s) das eine Info zum beenden des Thread zu lange bräuchte um den Thread zu stopen.

Zeitaufwändige Funktionen: CreateNetworkServer(), OpenNetworkConnection() [wenn Server nicht existiert] und andere Netzwerkdurchsuchende Befehle.

___
If the target thread owns a critical section, the critical section will not be released.
Das wäre der einzige Punkt der bei mir zutreffen würde, alle anderen Dinge habe ich vom Hauptprogramm kontrolliert oder benutze ich nicht.

Aber was ist nun mit der 2. Frage ?
EnterCriticalSection_(@Mutex)
LeaveCriticalSection_(@Mutex)
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Such mal nach dem Thread "KillThread reisst alles mit", aus dem mein schlauer SPruch in Winduff's Signatur stammt.
Aber bitte kill denThread nicht... :lol:

Dort wird dein Problem aufgegriffen.
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
mk-soft
Beiträge: 3845
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag von mk-soft »

STARGÅTE hat geschrieben: 1. die Globale Variable [MyThreadStop] ist in dem CODE ungesichert.
also würde dies auch in Ausnahmefällen zum absturtz führen.
Die Globale Variable wird von Thread nur gelesen und somit sicher.
Wie man mit Globalen Variablen sicher umgeht eine andere sache.

FF :wink:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

Thread nur gelesen und somit sicher
das dache ich auch ^^

Aber auch lesen reicht schon aus. denn MyThreadStop wird ja im Hauptprogramm auf #True gesetzt und genau zu diesem Schriebzeitpunkt könnte ja ein Thread gerade lesen. ERROR !!

hmm.

Mein Programm läuft nun mit CriticalSection_() simlich sicher. aber seltsamerweise schreiben sich bestimmte Strings die ÜBERHAUPT nix mit den Threads zu tuen haben einfach um :o

Ich verstehe die PCs nicht mehr :freak:
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

STARGÅTE hat geschrieben:Aber auch lesen reicht schon aus. denn MyThreadStop wird ja im Hauptprogramm auf #True gesetzt und genau zu diesem Schriebzeitpunkt könnte ja ein Thread gerade lesen. ERROR !!
Das dachte sich auch ein kluger Kopf im PB-Team und erfand dafür den "Threadsafe"-Modus, der genau das verhindert. :wink:

Ansonsten wüsste ich momentan keine gute Möglichkeit, einen Thread schonend zu beenden.
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
freak
PureBasic Team
Beiträge: 766
Registriert: 29.08.2004 00:20
Wohnort: Stuttgart

Beitrag von freak »

Zugriffe auf einfache typen (wie byte, word, long, float. NICHT aber double, quad, string)
sind "atomic", d.h. die Ausführung des Threads kann nicht unterbrochen werden während die Variable "halb" geschrieben ist.

Es ist also kein Problem wenn mehrere Threads auf eine solche globale Variable zugreifen (auch schreiben),
nur Dinge wie folgendes sind da gefährlich:

Code: Alles auswählen

If global_test < 5
  global_test + 1
EndIf
Hier kann ZWISCHEN dem "If" (wo global_test noch < 5 ist) und der Addition
ein anderer Thread die Variable ändern, was dann einen eventuell falschen Wert nach der addition ergibt,
da die If-Abfrage dann ja nicht mehr gestimmt hat. Hier muss man durch einen Mutex/CriticalSection absichern.

Befehle zur Thread-synchronisation wie EnterCriticalSection_(@Mutex) sind natürlich auch
absolut threadsicher (durch geeignete Mechanismen), sie wären ja sonst total nutzlos.

> Mein Programm läuft nun mit CriticalSection_() simlich sicher. aber
> seltsamerweise schreiben sich bestimmte Strings die ÜBERHAUPT nix mit
> den Threads zu tuen haben einfach um

Das PB Stringsystem ist NICHT threadsicher. Das arbeiten mit Strings, egal ob lokal
oder global funktioniert in threads nur wenn die threadsafe Option in den
Kompileroptionen aktiviert ist, sonst wird es immer Probleme geben.
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

> Das arbeiten mit Strings [...] funktioniert in threads nur wenn die threadsafe Option in den Kompileroptionen aktiviert ist
Problem: STARGATE benutzt noch PB 3.3...
Eine Möglichkeit, die mir hier nur einfällt wäre, Strings nicht in Vairablen, sondern in ein AllocateMemory() zu packen, ist aber sehr umständlich.
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Antworten