Page 1 of 1

Very slow loop and don't know why :(

Posted: Wed Sep 30, 2020 8:42 am
by Walko
Hello,

So first of all I am an extreme beginner in Purebasic and programming in general.

I found on this forum very nice example for handling serial port that works very well.
Now, I need to add some stuff to do inside the infinite loop but It seems that the loop is very very slow.

I just add to this found example a global variable and the ElapsedMilliseconds() function to see how fast the loop executes.
It seems that the execution speed is fast when I click a button ( or an event ), it seems to unlock something.

Do you know why and how to fix this ?

Thank you very much :)

Code: Select all

XIncludeFile "serial3.pbf"

EnableExplicit

#COMMaxPorts = 30

Enumeration #PB_Event_FirstCustomValue
  #ComThread_Started
  #ComThread_ByteReceived
  #ComThread_LineReceived
  #ComThread_Finished
EndEnumeration

Enumeration
  #SendString
  #SendButton
  #ReceiveText
  #ReceiveEdit
EndEnumeration

Global val

Structure ThreadParameterStructure
  Thread.i
  Semaphore.i
  Com$
  Com.i
  Receive$
  Exit.i
EndStructure


Global NewList COMUsablePorts.s()


Procedure COMGetAvailablePorts()

  Protected NewList COMPortNameList.s()
  Protected i.i, Directory.i, Com.i
 
 
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    For i = 1 To #COMMaxPorts
      AddElement(COMPortNameList())
      COMPortNameList() = "COM" + Str(i)
    Next i
  CompilerEndIf
 
  ForEach COMPortNameList()
    Com = OpenSerialPort(#PB_Any, COMPortNameList(), 115200, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1, 1)
    If Com
      AddElement(COMUsablePorts())
      COMUsablePorts() = COMPortNameList()
      CloseSerialPort(Com)
    EndIf
  Next
 
  FreeList(COMPortNameList())
 
EndProcedure


Procedure ComThread(*Parameter.ThreadParameterStructure)
 
  Protected Byte.a, ReceivedBytes.i
 
 
  PostEvent(#ComThread_Started)
 
  *Parameter\Com = OpenSerialPort(#PB_Any, *Parameter\Com$, 115200, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1024, 1024)
  If *Parameter\Com
   
    WriteSerialPortString(*Parameter\Com, "hello")
   
    Repeat
      If AvailableSerialPortInput(*Parameter\Com)
        If ReadSerialPortData(*Parameter\Com, @Byte, 1) = 1
          ReceivedBytes + 1
          PostEvent(#ComThread_ByteReceived, 0, 0, 0, ReceivedBytes)
          If Byte = #CR
            PostEvent(#ComThread_LineReceived)
            WaitSemaphore(*Parameter\Semaphore)
          Else
            *Parameter\Receive$ + Chr(Byte)
          EndIf
        EndIf
      Else
        Delay(10)
      EndIf
    Until *Parameter\Exit
   
    CloseSerialPort(*Parameter\Com)
   
  EndIf
 
  PostEvent(#ComThread_Finished)
 
EndProcedure


Define.i Event, Exit
Define ThreadParameter.ThreadParameterStructure

COMGetAvailablePorts()

OpenMain_menu()

ForEach COMUsablePorts()
  AddGadgetItem(#ComCombo, -1, COMUsablePorts())
Next
SetGadgetState(#ComCombo, 0)

ThreadParameter\Semaphore = CreateSemaphore()

Repeat
 
  Event = WaitWindowEvent()
 
  Select Event
    Case #ComThread_Started
      SetGadgetText(#StartButton, "Disconnect")
      DisableGadget(#ComCombo, #True)
     
    Case #ComThread_ByteReceived
      StatusBarText(0, 1, Str(EventData()), #PB_StatusBar_Center)
     
    Case #ComThread_LineReceived
      AddGadgetItem(#ReceiveText, -1, ThreadParameter\Receive$)
      ThreadParameter\Receive$ = ""
      SignalSemaphore(ThreadParameter\Semaphore)
     
    Case #ComThread_Finished
      SetGadgetText(#StartButton, "Start")
      DisableGadget(#ComCombo, #False)
     
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #StartButton
          If GetGadgetText(#StartButton) = "Start"

            ThreadParameter\Com$ = GetGadgetText(#ComCombo)
            ThreadParameter\Exit = #False
            ThreadParameter\Thread = CreateThread(@ComThread(), @ThreadParameter)
          Else
            ThreadParameter\Exit = #True
          EndIf
         
        Case #SendButton
          WriteSerialPortString(ThreadParameter\Com, GetGadgetText(#SendString))
         
      EndSelect
     
    Case #PB_Event_CloseWindow
      Exit = #True
     
  EndSelect
  
val = ElapsedMilliseconds()
Debug val 
 
Until Exit



If IsThread(ThreadParameter\Thread)
  ThreadParameter\Exit = #True
  If WaitThread(ThreadParameter\Thread, 3000) = 0
    KillThread(ThreadParameter\Thread)
  EndIf
EndIf

FreeSemaphore(ThreadParameter\Semaphore)

Re: Very slow loop and don't know why :(

Posted: Wed Sep 30, 2020 9:42 am
by TI-994A
Walko wrote:...I need to add some stuff to do inside the infinite loop but It seems that the loop is very very slow...
The event loop is technically not an infinite loop. It stops and waits for the command, WaitWindowEvent(), to receive events before executing the loop.

Re: Very slow loop and don't know why :(

Posted: Wed Sep 30, 2020 10:23 am
by HeX0R
Better use this to find available COM ports.
It will also show virtual COM ports, which usually are not named "COMx"

Re: Very slow loop and don't know why :(

Posted: Wed Sep 30, 2020 10:54 am
by Walko
Hello,

Thank you for your help.
I will look at your code :)

BTW, I solve my problem by using AddWindowTimer() :D