GetClipboardText() im Thread fuehrt zu Crash

Für allgemeine Fragen zur Programmierung mit PureBasic.
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: GetClipboardText() im Thread fuehrt zu Crash

Beitrag von ccode_new »

mk-soft hat geschrieben:Clipboard funktionen im Thread aufrufen geht nicht sicher.
Eigentlich schon! Nur man kann hierbei ja nicht intern eingreifen.

Woher weiß ich wann die Funktion fertig ist, wenn diese dabei asynchron läuft.

Also eigentlich müsste es heißen:

"Die PureBasic-Clipboard-Funktionen im Thread aufrufen geht unter PureBasic nicht sicher unter Linux."

Aber wofür gibt es den dein tolles Modul. :mrgreen:
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Benutzeravatar
mk-soft
Beiträge: 3701
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: GetClipboardText() im Thread fuehrt zu Crash

Beitrag von mk-soft »

Alles was mit PostEvent(...) versendet wird läuft im Message-Buffer von PB auf und wird erst beim Aufruf von WaitWindowEvent(...) verarbeitet.
Somit läuft es im Main-Scope.

Code: Alles auswählen

;-TOP

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

;-Begin Of SendEvent

; Comment : SendEvent
; Author  : mk-soft
; Version : v1.06
; Create  : unknown
; Update  : 07.08.2016

;- Structure
Structure udtSendEvent
  Signal.i
  Result.i
  *pData
EndStructure

; ---------------------------------------------------------------------------------------

Procedure SendEvent(Event, Window = 0, Object = 0, EventType = 0, pData = 0, Semaphore = 0)
  
  Protected MyEvent.udtSendEvent, result
  
  With MyEvent
    If Semaphore
      \Signal = Semaphore
    Else
      \Signal = CreateSemaphore()
    EndIf
    \pData = pData
    PostEvent(Event, Window, Object, EventType, @MyEvent)
    WaitSemaphore(\Signal)
    result = \Result
    If Semaphore = 0
      FreeSemaphore(\Signal)
    EndIf
  EndWith
  
  ProcedureReturn result
  
EndProcedure

; ---------------------------------------------------------------------------------------

Procedure SendEventData(*MyEvent.udtSendEvent)
  ProcedureReturn *MyEvent\pData
EndProcedure

; ---------------------------------------------------------------------------------------

Procedure DispatchEvent(*MyEvent.udtSendEvent, result)
  *MyEvent\Result = result
  SignalSemaphore(*MyEvent\Signal)
EndProcedure

;- End Of SendEvent

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

;- Example

EnableExplicit

; Constant
Enumeration ;Window
  #Main
EndEnumeration

Enumeration ; Menu
  #Menu
EndEnumeration

Enumeration ; MenuItems
  #MenuExitApplication
EndEnumeration

Enumeration ; Gadgets
  #List
  #Edit
EndEnumeration

Enumeration ; Statusbar
  #Status
EndEnumeration

; Global Variable
Global ExitApplication

; Functions
Procedure UpdateWindow()
  
  Protected x, y, dx, dy, menu, status
  
  menu = MenuHeight()
  If IsStatusBar(#Status)
    status = StatusBarHeight(#Status)
  Else
    status = 0
  EndIf
  x = 0
  y = 0
  dx = WindowWidth(#Main)
  dy = WindowHeight(#Main) - menu - status
  ResizeGadget(#List, x, y, dx, dy)
  
EndProcedure

; -----------------------------------------------------------------------------

Enumeration EventCustomValue #PB_Event_FirstCustomValue
  #MyEvent_GetClipbord
  #MyEvent_SetClipboard
  #MyEvent_AddText
EndEnumeration

Procedure DoSetClipboard()
  Protected MyEvent, *text.String
  MyEvent = EventData()
  *text = SendEventData(MyEvent)
  SetClipboardText(*text\s)
  DispatchEvent(MyEvent, 1)
EndProcedure

Procedure DoGetClipboard()
  Protected MyEvent, *text.String, len
  MyEvent = EventData()
  *text = SendEventData(MyEvent)
  *text\s = GetClipboardText()
  len = Len(*text\s)
  If len
    ClearClipboard()
  EndIf
  DispatchEvent(MyEvent, len)
EndProcedure

Procedure DoAddText()
  Protected MyEvent, *text.String
  MyEvent = EventData()
  *text = SendEventData(MyEvent)
  AddGadgetItem(#List, -1, *text\s)
  DispatchEvent(MyEvent, 1)
EndProcedure

BindEvent(#MyEvent_GetClipbord, @DoGetClipboard())
BindEvent(#MyEvent_SetClipboard, @DoSetClipboard())
BindEvent(#MyEvent_AddText, @DoAddText())

; -----------------------------------------------------------------------------

Structure udtThread
  ThreadID.i
  Exit.i
EndStructure

Global Thread1.udtThread

Procedure thWork(*data.udtThread)
  Protected result, text.string
  
  Repeat
    result = SendEvent(#MyEvent_GetClipbord, 0, 0, 0, text)
    If result
      SendEvent(#MyEvent_AddText, 0, 0, 0, text)
    EndIf
    Delay(1000)
  Until *data\Exit
  
EndProcedure

; -----------------------------------------------------------------------------

; Main
Procedure Main()
  
  Protected event, style, dx, dy
  
  style = #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget
  dx = 800
  dy = 600
  
  If OpenWindow(#Main, #PB_Ignore, #PB_Ignore, dx, dy, "Main", style)
    
    ; Enable Fullscreen
    CompilerIf #PB_Compiler_OS = #PB_OS_MacOS 
      Protected NewCollectionBehaviour
      NewCollectionBehaviour = CocoaMessage(0, WindowID(#Main), "collectionBehavior") | $80
      CocoaMessage(0, WindowID(#Main), "setCollectionBehavior:", NewCollectionBehaviour)
    CompilerEndIf
    
    ; Menu
    CreateMenu(#Menu, WindowID(#Main))
    MenuTitle("Ablage")
    MenuItem(#MenuExitApplication, "Be&enden")
    ; Gadgets
    ListViewGadget(#List, 0, 0, dx, dy)
    
    ; Statusbar
    CreateStatusBar(#Status, WindowID(#Main))
    AddStatusBarField(#PB_Ignore)
    
    UpdateWindow()
    
    Thread1\ThreadID = CreateThread(@thWork(), thread1)
    
    ; Main Loop
    Repeat
      event = WaitWindowEvent()
      Select event
        Case #PB_Event_Menu
          Select EventMenu()
              CompilerIf #PB_Compiler_OS = #PB_OS_MacOS   
              Case #PB_Menu_About
                
              Case #PB_Menu_Preferences
                
              Case #PB_Menu_Quit
                ExitApplication = #True
              CompilerEndIf
              
            Case #MenuExitApplication
              ExitApplication = #True
          EndSelect
          
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #List
              
            Case #Edit
              
          EndSelect
          
        Case #PB_Event_SizeWindow
          Select EventWindow()
            Case #Main
              UpdateWindow()
              
          EndSelect
          
        Case #PB_Event_CloseWindow
          Select EventWindow()
            Case #Main
              ExitApplication = #True
              
          EndSelect
          
      EndSelect
      
    Until ExitApplication
    
    ; Warten das der Thread beendet ist
    Thread1\Exit = #True
    Repeat 
      WaitWindowEvent(100)
      If IsThread(Thread1\ThreadID) = 0
        Break
      EndIf
    ForEver
    
  EndIf
  
EndProcedure : Main()

End

[/size]
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
mk-soft
Beiträge: 3701
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: GetClipboardText() im Thread fuehrt zu Crash

Beitrag von mk-soft »

P.S. Wozu ist mein Modul ThreadToGUI

Um Threads beim senden von String nicht zu blockieren, werden für den String immer Speicher angefordert und den Zeiger auf dem String mit PostEvent versendet.
Im Main-Scope, wo WaitWindowEvent(...) aufgerufen wird, wird das gesendete eigene Event verarbeitet und der Speicher für den String wieder freigegeben.

Wird eine Rückantwort im Thread benötigt, werden die Daten mit einem Semaphore versehen und mit PostEvent versendet. In Main-Scope (Aufruf WaitWindowEvent) werden die Daten aufgefüllt und mit dem Semaphore bestätigt das die Daten bereit sind.

P.P.S
Ohne dem Aufruf von WaitWindowEvent(...) werden die Event die mit BindEvent an einer Procedure gebunden werden auch nicht verarbeitet.

Alles was mit GUI zu tun hat muss bei MacOS und Linux im MainScope verarbeitet werden. Warum das so ist kann ich nicht sagen.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
Programie
Beiträge: 1280
Registriert: 06.08.2005 22:56
Computerausstattung: https://www.sysprofile.de/id160800
Wohnort: Gernsbach
Kontaktdaten:

Re: GetClipboardText() im Thread fuehrt zu Crash

Beitrag von Programie »

mk-soft hat geschrieben:Alles was mit GUI zu tun hat muss bei MacOS und Linux im MainScope verarbeitet werden. Warum das so ist kann ich nicht sagen.
Ist das eine Einschraenkung von PB oder von macOS und Linux?
BildBildBildBild
Benutzeravatar
DarkSoul
Beiträge: 689
Registriert: 19.10.2006 12:51

Re: GetClipboardText() im Thread fuehrt zu Crash

Beitrag von DarkSoul »

@ccode_new:
Dass deines immer perfekt synchron ist, ist auch logisch, da du den Sinn und Zweck von Threads perfekt ausgehebelt hast... :mrgreen: :mrgreen:

Ist GetClipboardText() überhaupt eine GUI-Funktion?
Bild
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: GetClipboardText() im Thread fuehrt zu Crash

Beitrag von ccode_new »

Naja, wenn die GUI (Fenster, Msg-Box, etc.) und die Clipboard-Funktionen nun mal asynchron laufen, dann ist dein aufgerufener Thread schon fertig, bevor die eigentlichen Funktionen fertig sind.

Diese haben eine eigene Eventschleife zu beachten.

Oder verarbeitest du z.B. bei einer MsgBox das Event beim Klick auf den "OK"-Button in einem Programm selber ?
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Benutzeravatar
mk-soft
Beiträge: 3701
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: GetClipboardText() im Thread fuehrt zu Crash

Beitrag von mk-soft »

DarkSoul hat geschrieben:@ccode_new:
Ist GetClipboardText() überhaupt eine GUI-Funktion?
Ich weis nur das es mit Threads unter Linux nicht funktioniert und zum Crash führte.
Es war mal eine Anfrage des wegen und habe danach die Verarbeitung vom Clipboard zum Modul ThreadToGUI hinzugefügt.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: GetClipboardText() im Thread fuehrt zu Crash

Beitrag von ccode_new »

Zur Angabe bei Threads steht bei GTK folgendes:
For thread safety, GDK relies on the thread primitives in GLib, and on the thread-safe GLib main loop.

GLib is completely thread safe (all global data is automatically locked), but individual data structure instances are not automatically locked for performance reasons. So e.g. you must coordinate accesses to the same GHashTable from multiple threads.

GTK+, however, is not thread safe. You should only use GTK+ and GDK from the thread gtk_init() and gtk_main() were called on. This is usually referred to as the “main thread”.

Signals on GTK+ and GDK types, as well as non-signal callbacks, are emitted in the main thread.

You can schedule work in the main thread safely from other threads by using gdk_threads_add_idle() and gdk_threads_add_timeout():

.....
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Benutzeravatar
Programie
Beiträge: 1280
Registriert: 06.08.2005 22:56
Computerausstattung: https://www.sysprofile.de/id160800
Wohnort: Gernsbach
Kontaktdaten:

Re: GetClipboardText() im Thread fuehrt zu Crash

Beitrag von Programie »

OK, dann verstehe ich das so, dass das keine Einschraenkung von PB ist sondern von GDK/GTK.
BildBildBildBild
Benutzeravatar
mk-soft
Beiträge: 3701
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: GetClipboardText() im Thread fuehrt zu Crash

Beitrag von mk-soft »

So sehe ich das auch und somit macht mein Modul ThreadToGUI sinn 8)
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Antworten