MessagRequester and Thread

Mac OSX specific forum
loulou2522
Enthusiast
Enthusiast
Posts: 501
Joined: Tue Oct 14, 2014 12:09 pm

MessagRequester and Thread

Post by loulou2522 »

Is-it possible to use cocoa message to simulate a a function like messageRequester in a thread ?
THanks
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: MessagRequester and Thread

Post by wilbert »

loulou2522 wrote:Is-it possible to use cocoa message to simulate a a function like messageRequester in a thread ?
THanks
Something like this ?
http://www.purebasic.fr/english/viewtop ... 86#p465186
http://www.purebasic.fr/english/viewtop ... 29#p465129
It uses the NSAlert class.
Windows (x64)
Raspberry Pi OS (Arm64)
loulou2522
Enthusiast
Enthusiast
Posts: 501
Joined: Tue Oct 14, 2014 12:09 pm

Re: MessagRequester and Thread

Post by loulou2522 »

Thanks but i ever try these function and the problem is always the same in thread
User avatar
mk-soft
Always Here
Always Here
Posts: 5401
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: MessagRequester and Thread

Post by mk-soft »

Another way over PostEvent for all OS

Its a part from ThreadToGUI

Code: Select all

;-TOP
;
; MessageRequester aus Thread aufrufen
; mk-soft, v1.02, 16.03.2018

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

CompilerIf #PB_Compiler_Thread = 0
  CompilerError "Option Threadsafe aktivieren"
CompilerEndIf

Enumeration EventCustomValue #PB_Event_FirstCustomValue
  ; Nothing
EndEnumeration
  
Enumeration EventCustomValue
  #MyEvent_MessageRequester
EndEnumeration

Structure udtMessageRequester
  Signal.i
  Result.i
  Title.s
  Text.s
  Flags.i
EndStructure

Global LockMessageRequester = CreateMutex()

Procedure thMessageRequester(Title.s, Text.s, Flags=0)
  Protected *data.udtMessageRequester, result.i
  With *data
    *data = AllocateStructure(udtMessageRequester)
    If *data
      \Signal = CreateSemaphore()
      \Title = Title
      \Text = Text
      \Flags = Flags
      LockMutex(LockMessageRequester)
      PostEvent(#MyEvent_MessageRequester, 0, 0, 0, *data)
      WaitSemaphore(\Signal)
      UnlockMutex(LockMessageRequester)
      FreeSemaphore(\Signal)
      result = \Result
      FreeStructure(*data)
      ProcedureReturn result
    Else
      ProcedureReturn -1 ; Out Of Memory
    EndIf
  EndWith
EndProcedure

Procedure DispatchMessageRequester()
  Protected *data.udtMessageRequester
  With *data
    *data = EventData()
    If *data
      \Result = MessageRequester(\Title, \Text, \Flags)
      SignalSemaphore(\Signal)
    EndIf
  EndWith
EndProcedure

BindEvent(#MyEvent_MessageRequester, @DispatchMessageRequester())

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

CompilerIf #PB_Compiler_IsMainFile
  
  Procedure thMessage(Nummer)
    Protected r1
    Repeat
      Delay(1000)
      r1 = thMessageRequester("Frage", "Thread Nummer " + Nummer +  " beenden?", #PB_MessageRequester_YesNo | #PB_MessageRequester_Info)
    Until r1 = #PB_MessageRequester_Yes
  EndProcedure
  
  If OpenWindow(0, #PB_Ignore, #PB_Ignore, 200, 80, "Thread Test")
    CreateThread(@thMessage(), 1)
    CreateThread(@thMessage(), 2)
    CreateThread(@thMessage(), 3)
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Break
      EndSelect
    ForEver
  EndIf
  
CompilerEndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
loulou2522
Enthusiast
Enthusiast
Posts: 501
Joined: Tue Oct 14, 2014 12:09 pm

Re: MessagRequester and Thread

Post by loulou2522 »

Thanks MKsoft
IN fact here is what I want to do

Code: Select all

Procedure MyThread(msDelay.i)
  ;===============================
  Repeat
    Delay(msDelay)
    UniKey_User_Logoff(@handle)    
    retcode.l = UniKey_Find (@Handle, @p1, @p2) 
    
    If FormatNumber(retcode,0) = "200"
    ;MessageRequesterEx("Icon demo 4", "Requester with stop icon", "'stop'")
  ;MessageRequester("Conversion Fichier Suisse","Dongle de protection non trouvé"+#LF$+"Veuillez le reconnecter"+#LF$+"Puis relancer le programme",#PB_MessageRequester_Ok|#PB_MessageRequester_Error )
      UniKey_User_Logoff(@handle)
      End    
    Else 
      UniKey_User_Logoff(@handle)  
      retcode.l = UniKey_Find (@Handle, @p1, @p2) 
      If retcode = 0
        retcode = UniKey_User_Logon(@handle.w, @p11.w,@p12.w)
        Debug Str(retcode)+ "Ligne 48"
        If  retcode <> 0   
          MessageRequester("Conversion Fichier Suisse","Mot de passe du dongle erroné"+#LF$+"Veuilez revoir avec votre administrateur"+#LF$+ "Abandon programme",#PB_MessageRequester_Ok|#PB_MessageRequester_Error)
          UniKey_User_Logoff(@handle)
          End    
        EndIf
      Else 
        If retcode <> 0 
        ;MessageRequesterEx("Icon demo 4", "Requester with stop icon", "'stop'")
    
        ;  MessageRequester("Conversion Fichier Suisse","Dongle de protection non trouvé"+#LF$+"Veuillez le reconnecter"+#LF$+"Puis relancer le programme",#PB_MessageRequester_Ok|#PB_MessageRequester_Error )
          UniKey_User_Logoff(@handle)
          End 
        EndIf 
      EndIf 
    EndIf   
    ForEver
  EndProcedure
  
  Threadedun = CreateThread(@MyThread(), 3000)
It' a procedure that's verify every 3000 that'a a dongle is connected. If not I want to use Messagerequester and after quit the program

Code: Select all

 MessageRequester("Conversion Fichier Suisse","Mot de passe du dongle erroné"+#LF$+"Veuilez revoir avec votre administrateur"+#LF$+ "Abandon programme",#PB_MessageRequester_Ok|#PB_MessageRequester_Error)
          UniKey_User_Logoff(@handle)
          End    
User avatar
mk-soft
Always Here
Always Here
Posts: 5401
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: MessagRequester and Thread

Post by mk-soft »

When the program ends, the thread is also terminated.
So only works if you start a second program.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
loulou2522
Enthusiast
Enthusiast
Posts: 501
Joined: Tue Oct 14, 2014 12:09 pm

Re: MessagRequester and Thread

Post by loulou2522 »

in fact I need to explain what I want to do
I launch a program with is protected by a dongle.
Every 3000 ms I test if the dongle is always connected and if not in the thread
I display a warning message and after I quit the program
With pure basic on Mac OS X the thread can't accept MessageRequester and generate an error.
Fred
Administrator
Administrator
Posts: 16684
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: MessagRequester and Thread

Post by Fred »

Just post an event to your main thread and handle the event from your main event loop.
User avatar
mk-soft
Always Here
Always Here
Posts: 5401
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: MessagRequester and Thread

Post by mk-soft »

You need always a Window and an EventLoop. The window can be invisible.

Code: Select all

;-TOP
;
; MessageRequester aus Thread aufrufen
; mk-soft, v1.02, 16.03.2018

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

CompilerIf #PB_Compiler_Thread = 0
  CompilerError "Option Threadsafe aktivieren"
CompilerEndIf

Enumeration EventCustomValue #PB_Event_FirstCustomValue
  ; Nothing
EndEnumeration
  
Enumeration EventCustomValue
  #MyEvent_MessageRequester
EndEnumeration

Structure udtMessageRequester
  Signal.i
  Result.i
  Title.s
  Text.s
  Flags.i
EndStructure

Global LockMessageRequester = CreateMutex()

Procedure DoMessageRequester(Title.s, Text.s, Flags=0)
  Protected *data.udtMessageRequester, result.i
  With *data
    *data = AllocateStructure(udtMessageRequester)
    If *data
      \Signal = CreateSemaphore()
      \Title = Title
      \Text = Text
      \Flags = Flags
      LockMutex(LockMessageRequester)
      PostEvent(#MyEvent_MessageRequester, 0, 0, 0, *data)
      WaitSemaphore(\Signal)
      UnlockMutex(LockMessageRequester)
      FreeSemaphore(\Signal)
      result = \Result
      FreeStructure(*data)
      ProcedureReturn result
    Else
      ProcedureReturn -1 ; Out Of Memory
    EndIf
  EndWith
EndProcedure

Procedure DispatchMessageRequester()
  Protected *data.udtMessageRequester
  With *data
    *data = EventData()
    If *data
      \Result = MessageRequester(\Title, \Text, \Flags)
      SignalSemaphore(\Signal)
    EndIf
  EndWith
EndProcedure

BindEvent(#MyEvent_MessageRequester, @DispatchMessageRequester())

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

CompilerIf #PB_Compiler_IsMainFile
  
  Global ExitApplication
  
  Procedure thMessage(Nummer)
    Protected r1
    Repeat
      Delay(3000)
      r1 = DoMessageRequester("Frage", "Thread " + Nummer +  " exit application?", #PB_MessageRequester_YesNo | #PB_MessageRequester_Error)
    Until r1 = #PB_MessageRequester_Yes
    ExitApplication = #True
  EndProcedure
  
  If OpenWindow(0, #PB_Ignore, #PB_Ignore, 200, 80, "Hide window", #PB_Window_NoGadgets | #PB_Window_Invisible)
    CreateThread(@thMessage(), 1)
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Break
      EndSelect
    Until ExitApplication
  EndIf
  
CompilerEndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
mk-soft
Always Here
Always Here
Posts: 5401
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: MessagRequester and Thread

Post by mk-soft »

Ok...

Simple example with PostEvent

Edit

Code: Select all

Global ExitApplication

Enumeration EventCustomValue #PB_Event_FirstCustomValue
  ; Nothing
EndEnumeration
  
Enumeration EventCustomValue
  #MyEvent_MissingDongle
EndEnumeration

Procedure thMessage(Nummer)
  Protected r1, dongle
  
  Repeat
    Delay(3000)
    dongle = 0
    If Not dongle
      PostEvent(#MyEvent_MissingDongle)
      Break
    EndIf
  ForEver
EndProcedure

If OpenWindow(0, #PB_Ignore, #PB_Ignore, 200, 80, "Window", #PB_Window_SystemMenu)
  CreateThread(@thMessage(), 1)
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        Break
      Case #MyEvent_MissingDongle
        MessageRequester("Stop", "Missing dongle. Exit application!", #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
        ExitApplication = #True
    EndSelect
  Until ExitApplication
EndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Fred
Administrator
Administrator
Posts: 16684
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: MessagRequester and Thread

Post by Fred »

Perfect way to do that @mk-soft
User avatar
TI-994A
Addict
Addict
Posts: 2512
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: MessagRequester and Thread

Post by TI-994A »

As Fred had mentioned, and according to mk-soft's code, this example demonstrates how to throw different messages without posting separate events for each:

Code: Select all

#msgBoxEvent = #PB_Event_FirstCustomValue

Procedure MyThread(msDelay.i)
;===============================
  Repeat
    Delay(msDelay)
    UniKey_User_Logoff(@handle)    
    retcode.l = UniKey_Find (@Handle, @p1, @p2) 
    
    If FormatNumber(retcode,0) = "200"
      PostEvent(#msgBoxEvent, 0, 0, 0, 1)
      UniKey_User_Logoff(@handle)
      End    
    Else 
      UniKey_User_Logoff(@handle)  
      retcode.l = UniKey_Find (@Handle, @p1, @p2) 
      If retcode = 0
        retcode = UniKey_User_Logon(@handle.w, @p11.w,@p12.w)
        Debug Str(retcode) + "Ligne 48"        
        If  retcode <> 0   
          PostEvent(#msgBoxEvent, 0, 0, 0, 2)
          UniKey_User_Logoff(@handle)
          End    
        EndIf
      Else 
        If retcode <> 0 
          PostEvent(#msgBoxEvent, 0, 0, 0, 3)
          UniKey_User_Logoff(@handle)
          End 
        EndIf 
      EndIf 
    EndIf   
  ForEver
EndProcedure

Threadedun = CreateThread(@MyThread(), 3000)

wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
mainWindow = OpenWindow(#PB_Any, 0, 0, 400, 100, "Threaded Message Box Handling", wFlags)
clockDisplay = TextGadget(#PB_Any, 0, 40, 400, 20, "Clock Display", #PB_Text_Center)
AddWindowTimer(mainWindow, clock, 1000)

Repeat
  Select WaitWindowEvent()
      
    Case #PB_Event_CloseWindow
      Select EventWindow()
        Case mainWindow
          appQuit = 1          
      EndSelect
      
    Case #PB_Event_Timer
      Select EventTimer()
        Case clock
          SetGadgetText(clockDisplay, FormatDate("%hh:%ii:%ss", Date()))
      EndSelect  
      
    Case #msgBoxEvent
      Select EventData()
        Case 1
          message$ = "Dongle de protection non trouvé" + #LF$ +
                     "Veuillez le reconnecter" + #LF$ + "Puis relancer le programme"
        Case 2
          message$ = "Mot de passe du dongle erroné" + #LF$ +
                     "Veuilez revoir avec votre administrateur" + #LF$ + "Abandon programme"
        Case 3
          message$ = "Dongle de protection non trouvé" + #LF$ + 
                     "Veuillez le reconnecter" + #LF$ + "Puis relancer le programme"
      EndSelect
      
      MessageRequester("Conversion Fichier Suisse", message$,
                       #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
  EndSelect
  
Until appQuit
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
User avatar
mk-soft
Always Here
Always Here
Posts: 5401
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: MessagRequester and Thread

Post by mk-soft »

Or 'DoMessageRequester(Title.s, Text.s, Flags=0)' direct from Thread. Modul ThreadToGUI
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
loulou2522
Enthusiast
Enthusiast
Posts: 501
Joined: Tue Oct 14, 2014 12:09 pm

Re: MessagRequester and Thread

Post by loulou2522 »

THanks mk_soft this works perfectly
I have another problem becaus this thread would be executed every 5000ms
But in this example the programm can't execute anymore thing because it is blocked in the repeat for the window.
How can i make othe part of code which has to be executed in the main programm ?
User avatar
mk-soft
Always Here
Always Here
Posts: 5401
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: MessagRequester and Thread

Post by mk-soft »

You need a own information window for this...

Here one example how to create a none blocked window over PostEvent...
I think you can modify this code for your demands

Code: Select all

;-TOP
;
; Comment : Thread Status Window
; Author  : mk-soft
; Version : v1.02
; Create  : 16.03.2018
; Update  :
;
; -----------------------------------------------------------------------------

EnableExplicit

CompilerIf #PB_Compiler_Thread = 0
  CompilerError "Use Compiler Option Threadsafe"
CompilerEndIf

Enumeration EventCustomValue #PB_Event_FirstCustomValue
  ; Nothing
EndEnumeration
  
Enumeration EventCustomValue
  #MyEvent_ThreadStatusOpen
  #MyEvent_ThreadStatusClose
  #MyEvent_ThreadStatusUpdate
EndEnumeration

Structure udtThreadStatus
  Signal.i
  Window.i
  Info.i
  Progress.i
  Cancel.i
  x.i
  y.i
  dx.i
  dy.i
  Title.s
  Text.s
  Button.s
  Min.i
  Max.i
  Value.i
EndStructure

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

Procedure DoOpenStatusWindow(x, y, dx, dy, Title.s, Text.s, Button.s="Cancel", Min=0, Max=100)
  Protected *data.udtThreadStatus
  With *data
    *data = AllocateStructure(udtThreadStatus)
    If *data
      \x = x
      \y = y
      \dx = dx
      \dy = dy
      \Title = Title
      \Text = Text
      \Button = Button
      \Min = Min
      \Max = Max
      \Signal = CreateSemaphore()
      PostEvent(#MyEvent_ThreadStatusOpen, 0, 0, 0, *data)
      WaitSemaphore(\Signal)
      If \Window
        ProcedureReturn *data
      Else
        FreeSemaphore(\Signal)
        FreeStructure(*data)
        ProcedureReturn 0 ; Error open windows
      EndIf
    Else
      ProcedureReturn 0 ; Out of Memory
    EndIf
  EndWith
EndProcedure

Declare DispatchTryCancelStatusWindow()

Procedure DispatchOpenStatusWindow()
  Protected *data.udtThreadStatus
  With *data
    *data = EventData()
    If *data
      \Window = OpenWindow(#PB_Any, \x, \y, \dx, \dy, \Title, #PB_Window_Tool)
      If \Window
        \Info = TextGadget(#PB_Any, 5, 5, \dx - 10, \dy - 65, \Text, #PB_Text_Center); | #PB_Text_Border) 
        \Progress = ProgressBarGadget(#PB_Any, 5, \dy - 55, \dx - 10, 20, \Min, \Max)
        \Cancel = ButtonGadget(#PB_Any, \dx / 2 - 60, \dy - 30, 120, 25, \Button)
        SetGadgetData(\Cancel, *data)
        BindGadgetEvent(\Cancel, @DispatchTryCancelStatusWindow())
      EndIf
      SignalSemaphore(\Signal)
    EndIf
  EndWith
EndProcedure

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

Procedure DoCloseStatusWindow(*Data.udtThreadStatus)
  With *Data
    If *Data
      PostEvent(#MyEvent_ThreadStatusClose, 0, 0, 0, *Data)
    EndIf
  EndWith
EndProcedure

Procedure DispatchCloseStatusWindow()
  Protected *data.udtThreadStatus
  With *data
    *data = EventData()
    If *data
      If IsWindow(\Window)
        CloseWindow(\Window)
      EndIf
      FreeSemaphore(\Signal)
      FreeStructure(*Data)
    EndIf
  EndWith
EndProcedure

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

Procedure TryCancelStatusWindow(*Data.udtThreadStatus)
  If *Data
    ProcedureReturn TrySemaphore(*Data\Signal)
  Else
    ProcedureReturn 0 
  EndIf
EndProcedure

Procedure DispatchTryCancelStatusWindow()
  Protected *data.udtThreadStatus
  With *data
    *data = GetGadgetData(EventGadget())
    If *data
      SignalSemaphore(\Signal)
    EndIf
  EndWith
EndProcedure

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

Procedure DoUpdateStatusWindow(*Data.udtThreadStatus, Value.i)
  With *Data
    If *Data
      \Value = Value
      PostEvent(#MyEvent_ThreadStatusUpdate, 0, 0, 0, *Data)
    EndIf
  EndWith
EndProcedure

Procedure DispatchUpdateStatusWindow()
  Protected *data.udtThreadStatus
  With *data
    *data = EventData()
    If *data
      If IsGadget(\Progress)
        SetGadgetState(\Progress, \Value)
      EndIf
    EndIf
  EndWith
EndProcedure

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

BindEvent(#MyEvent_ThreadStatusOpen, @DispatchOpenStatusWindow())
BindEvent(#MyEvent_ThreadStatusClose, @DispatchCloseStatusWindow())
BindEvent(#MyEvent_ThreadStatusUpdate, @DispatchUpdateStatusWindow())

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

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

;-Test

CompilerIf #PB_Compiler_IsMainFile
  
  Procedure thProgress(Nummer)
    Protected *Data, Text.s, Value
    
    Debug "Start Thread " + Nummer
    text = #LF$ + "Thread Hintergrund Status" + #LF$ + "Fertig in 20 Sekunden" + #LF$ + "Zum beenden abrechen"
    *Data = DoOpenStatusWindow(#PB_Ignore, #PB_Ignore, 300, 160, "Thread Nummer " + Nummer, Text); , "Abbrechen")
    
    Repeat
      Delay(500)
      value + 500
      DoUpdateStatusWindow(*Data, (Value / 200) % 100)
    Until TryCancelStatusWindow(*Data) Or Value >= 20000
    DoCloseStatusWindow(*Data)
    Debug "Ende Thread " + Nummer + " Value = " + Value
  EndProcedure
  
  If OpenWindow(0, #PB_Ignore, #PB_Ignore, 200, 80, "Thread Test")
    CreateThread(@thProgress(), 1)
    CreateThread(@thProgress(), 2)
    CreateThread(@thProgress(), 3)
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          If EventWindow() = 0
            Break
          EndIf
      EndSelect
    ForEver
  EndIf
  
CompilerEndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Post Reply