Seite 2 von 3
Re: GetClipboardText() im Thread fuehrt zu Crash
Verfasst: 05.12.2018 21:46
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.

Re: GetClipboardText() im Thread fuehrt zu Crash
Verfasst: 05.12.2018 22:33
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]
Re: GetClipboardText() im Thread fuehrt zu Crash
Verfasst: 05.12.2018 22:52
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.
Re: GetClipboardText() im Thread fuehrt zu Crash
Verfasst: 06.12.2018 00:17
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?
Re: GetClipboardText() im Thread fuehrt zu Crash
Verfasst: 06.12.2018 01:05
von DarkSoul
@ccode_new:
Dass deines immer perfekt synchron ist, ist auch logisch, da du den Sinn und Zweck von Threads perfekt ausgehebelt hast...
Ist GetClipboardText() überhaupt eine GUI-Funktion?
Re: GetClipboardText() im Thread fuehrt zu Crash
Verfasst: 06.12.2018 01:34
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 ?
Re: GetClipboardText() im Thread fuehrt zu Crash
Verfasst: 06.12.2018 02:22
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.
Re: GetClipboardText() im Thread fuehrt zu Crash
Verfasst: 06.12.2018 18:48
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():
.....
Re: GetClipboardText() im Thread fuehrt zu Crash
Verfasst: 06.12.2018 20:08
von Programie
OK, dann verstehe ich das so, dass das keine Einschraenkung von PB ist sondern von GDK/GTK.
Re: GetClipboardText() im Thread fuehrt zu Crash
Verfasst: 06.12.2018 23:25
von mk-soft
So sehe ich das auch und somit macht mein Modul ThreadToGUI sinn
