A Thread example:
Code: Select all
EnableExplicit
CompilerIf Not #PB_Compiler_Thread
MessageRequester("Info", "Enable Thread-Safe in compiler options!")
End
CompilerEndIf
Enumeration #PB_Event_FirstCustomValue
#Com_Event_RxBytes
#Com_Event_TxBytes
#Com_Event_RxComplete
#Com_Event_Exit
EndEnumeration
Structure ComParameterStructure
COM$
Thread.i
Semaphore.i
Mutex.i
Rx$
Tx$
Exit.i
EndStructure
Procedure ComThread(*Parameter.ComParameterStructure)
Protected.a Byte
Protected.i Port, RxLen, RxBytes, State
Protected Rx$
Port = OpenSerialPort(#PB_Any, *Parameter\COM$, 1200, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 128, 128)
If Port
Repeat
RxLen = AvailableSerialPortInput(Port)
If RxLen
While RxLen
If ReadSerialPortData(Port, @Byte, 1) = 1
RxBytes + 1
PostEvent(#Com_Event_RxBytes, 0, 0, 0, RxBytes)
Debug Byte
Select State
Case 0
If Byte = #CR
State + 1
Else
*Parameter\Rx$ + Chr(Byte)
EndIf
Case 1
If Byte = #LF
PostEvent(#Com_Event_RxComplete)
WaitSemaphore(*Parameter\Semaphore)
EndIf
State = 0
EndSelect
RxLen - 1
EndIf
Wend
ElseIf TryLockMutex(*Parameter\Mutex)
If Len(*Parameter\Tx$)
WriteSerialPortString(Port, *Parameter\Tx$, #PB_Ascii)
*Parameter\Tx$ = ""
EndIf
UnlockMutex(*Parameter\Mutex)
Else
Delay(3)
EndIf
Until *Parameter\Exit
CloseSerialPort(Port)
EndIf
PostEvent(#Com_Event_Exit)
EndProcedure
Define.i Event, Exit
Define ComParameter.ComParameterStructure
OpenWindow(0, 0, 0, 640, 480, "Com - Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
ButtonGadget(0, 10, 10, 80, 25, "Connect")
CreateStatusBar(0, WindowID(0))
AddStatusBarField(100)
AddStatusBarField(100)
AddStatusBarField(100)
AddStatusBarField(100)
StatusBarText(0, 0, "disconnected", #PB_StatusBar_Center)
StatusBarText(0, 1, "Rx: 0", #PB_StatusBar_Center)
StatusBarText(0, 2, "Tx: 0", #PB_StatusBar_Center)
ComParameter\COM$ = "COM9"
ComParameter\Semaphore = CreateSemaphore()
ComParameter\Mutex = CreateMutex()
Repeat
Event = WaitWindowEvent()
Select Event
Case #Com_Event_RxBytes
StatusBarText(0, 1, "Rx: " + Str(EventData()), #PB_StatusBar_Center)
Case #Com_Event_TxBytes
StatusBarText(0, 2, "Tx: " + Str(EventData()), #PB_StatusBar_Center)
Case #Com_Event_RxComplete
StatusBarText(0, 3, ComParameter\Rx$, #PB_StatusBar_Center)
Select ComParameter\Rx$
Case "ping"
LockMutex(ComParameter\Mutex)
ComParameter\Tx$ = "pong"
UnlockMutex(ComParameter\Mutex)
EndSelect
ComParameter\Rx$ = ""
SignalSemaphore(ComParameter\Semaphore)
Case #Com_Event_Exit
ComParameter\Exit = #False
SetGadgetText(0, "Connect")
StatusBarText(0, 0, "disconnected", #PB_StatusBar_Center)
Case #PB_Event_Gadget
Select EventGadget()
Case 0
If IsThread(ComParameter\Thread)
ComParameter\Exit = #True
Else
ComParameter\Thread = CreateThread(@ComThread(), @ComParameter)
If ComParameter\Thread
SetGadgetText(0, "Disconnect")
StatusBarText(0, 0, "connected", #PB_StatusBar_Center)
EndIf
EndIf
EndSelect
Case #PB_Event_CloseWindow
If IsThread(ComParameter\Thread)
ComParameter\Exit = #True
If WaitThread(ComParameter\Thread, 1000) = 0
KillThread(ComParameter\Thread)
EndIf
EndIf
FreeMutex(ComParameter\Mutex)
FreeSemaphore(ComParameter\Semaphore)
Exit = #True
EndSelect
Until Exit
If you want a stable program, than don't show any text direct from inside the thread.
Use always the way with PostEvent().
At least in Linux and OS X you run in big trouble if you do it directly.
Bernd