Announcement

Collapse
No announcement yet.

Comms response time vs focus

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Comms response time vs focus

    Hi,

    I have a small issue with a comms app that collects data from an instrument and displays it in a dialog running in a separate thread. The data in only a question of 140 bytes, all ASCII, and the comms receive procedure runs in its own thread.

    The app works well but slowly - the data arrives at 115.2kbaud and should take a maximum of 15ms to be transmitted however the time between reception and display is some 500ms. This latency can be reduced by a large factor if I move the main dialog, thus causing a repaint, or open any of the menus and leave the mouse within the menu area. Sounds to me as if the activity of any windows messages causes the app to run faster.

    All dialog controls and menus are dealt with in the dialog callback (i.e. there are no independent callbacks for any control or menu) and all the comms routines (reception, command interpreter etc.) run in a separate thread.

    Why should opening a menu or causing a repaint cause my comms thread to work faster? Is this known behaviour or simply something that I have done wrong?

    Anyone out there seen this type of behaviour before?

    John

  • #2
    Hi John,
    I usually deal with serial ports and yes I have and do see this problem all the time. You will notice if you just wiggle the mouse over your window you will receive data back even faster than just holding the mouse over the window without moving it.

    The problem I believe is the Message pump. Until there is a message "ANY MESSAGE" from windows, you will see that it does not loop back (or at least it appears that way if you watch it in debugger and do not touch or move anything.)

    I know I asked about it here somewhere recently and posted an example of what I was seeing. (now I just have to find it)

    (And yes, like you I have my port threaded so that it runs on its own.)

    Engineer's Motto: If it aint broke take it apart and fix it

    "If at 1st you don't succeed... call it version 1.0"

    "Half of Programming is coding"....."The other 90% is DEBUGGING"

    "Document my code????" .... "WHYYY??? do you think they call it CODE? "

    Comment


    • #3
      Hi John;

      Is your application passive, that is does it just wait for the attached device to collect the data and transmit it. Or does it send a command directing the device to collect and transmit data? Does the comm port use a hardware or software protocol to control flow of data?

      Comment


      • #4
        This thread discusses the issues involved in worker threads acquiring data then updating the display of the data in the Main GUI thread.
        http://www.powerbasic.com/support/pb...ad.php?t=40476

        There might be some useful clues there?
        Rgds, Dave

        Comment


        • #5
          If a message is queued (eg, the message you posted from worker thread function to update the screen) (assumed, code not shown) , you can force a thread switch with SwitchToThread() or "Sleep 0" (the WinAPI function, don't know if it applies to the PB SLEEP statement).

          When thread switch occurs it will be the turn of the GUI thread to pick up and 'do something' with the queued message.

          Or, just SEND the message to update instead of POSTing it.

          Regardless, trying to get optimal use of resources to both "update screen" and "gather info" IS going to be a "tuning" thing... that is, the correct solution will depend on a whole lot of things, like current computer load, number of services running, etc etc etc.
          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            Thanks for your replies

            Cliff,
            Yes I read that thread just after posting! Very interesting but no real solution. That doesn't bode well. I have written many serial apps with PB (starting with PB/DLL back in the 90's sometime) and VB of various flavours and have never really seen this tyoe of behaviour before. Mind you this is the first time that the response time is important - most of the old apps were passive, just waiting for input and calculating/displaying it but this one is active and must request new data after each reception.
            You're right, it does look like the message pump is "stalled" while there are no new messages so the thread simply slows down. It's tempting to request that the comms thread sends a message to the main dialog at every iteration and see where that gets me. So tempting that I might just try it - after all nothing else is working. Even setting the thread priority makes no difference, in whatever thread.

            Walter,
            Active (see above) with a proprietory protocol. The Comms thread uses a state machine to collect data as the number of data bytes is not known until the incoming "command" is read.

            Dave,
            Yes, thanks for the link. I've just read that. Very interesting and relevant. Now I just have to assimilate and inwardly digest. This calls for a cuppa I reckon

            Micheal,
            All the messages sent to dialogs (especially running on other threads) are sent rather than posted. Sorry about the lack of code - I know it makes it very difficult to suggest solutions - but it runs to several thousand lines and I'm not entirely sure what parts to censor to make it either readable (without having to spend the entire day doing so) or a valid example.
            According to the help file PB SLEEP 0 does exactly the same as the API Sleep(0) - it relinquishes the rest of the thread timeslice to other threads.
            ..and you're right of course - getting this app to do what I want it to do within the time limits that I need will require a fair amount of tuning and generally beating the OS into submission.

            I shall continue doing so...

            John

            Comment


            • #7
              John,
              you could try and take your COMMs routines out of the normal message loop and run them with a timer instead so they run at a more or less constant rate regardless of what else is going on.
              Code:
              'PBCC5 PProgram
              $INCLUDE "WIN32API.INC"
              DECLARE FUNCTION test( BYVAL uID AS LONG, BYVAL uMsg AS LONG, _
                                       BYVAL dwUser AS LONG, BYVAL dw1 AS LONG, BYVAL dw2 AS LONG) AS LONG
              
              GLOBAL COUNT AS LONG
              
              FUNCTION WINMAIN (BYVAL hInstance     AS LONG, _
                                BYVAL hPrevInstance AS LONG, _
                                BYVAL lpCmdLine           AS ASCIIZ PTR, _
                                BYVAL iCmdShow      AS LONG) AS LONG
              
              'start the timer
              '1=milliseconds between triggers, 0=maximum timer resolution, test=the routine to call
              TimerHandle& = timeSetEvent ( BYVAL 1, BYVAL 0, CODEPTR(test), BYVAL 0&, BYVAL %TIME_PERIODIC)
              
              PRINT "press a key to end."
              'This DO/LOOP would be replaced by your normal message loop.
              DO
                 LOCATE 10,10
                 PRINT "Time=";FORMAT$(count&/1000,"#######.###");"secs."
                 SLEEP 1
                 LOOP UNTIL INSTAT
              
                 timeKillEvent TimerHandle&
              
              END FUNCTION
              
              FUNCTION test ( BYVAL uID AS LONG, BYVAL uMsg AS LONG, _
                                      BYVAL dwUser AS LONG, BYVAL dw1 AS LONG, BYVAL dw2 AS LONG) AS LONG
              'this is the routine that is run everytime the timer triggers
              'you can do you COMMs processing here
              
                    INCR COUNT
              END FUNCTION
              Paul.

              Comment


              • #8
                I still think the obvious answer is, "update the screen less frequently."

                As a user, I don't care to see 1 percent, 2 percent, 3 percent.... but 10 percent,20 percent, 30 percent would be nice.

                Bottom line, I'll bet in 90+ percent of these types of applications I can't do anything until it gets to 100% anyway.....

                MCM
                Michael Mattias
                Tal Systems (retired)
                Port Washington WI USA
                [email protected]
                http://www.talsystems.com

                Comment


                • #9
                  Hi all,

                  Problem solved! Turns out that I was running the command interpreter within the comms thread (as it should be really as the comms has nothing to do while the interpreter is running) but it calls various procedures that update the main thread's GUI. Bad, bad, bad.
                  I now run the command interpreter within the main thread and send a message to the GUI telling it that data had been received and is ready to be interpreted. Whaddayaknow - lots of fast comms and updates

                  Thanks for all your help guys.

                  John

                  Comment


                  • #10
                    now run the command interpreter within the main thread and send a message to the GUI telling it that data had been received and is ready to be interpreted. Whaddayaknow - lots of fast comms and updates
                    Take out the calls to the command interpreter by using the provided intrinsic functions and I'll bet it will be even smoother and faster.
                    Michael Mattias
                    Tal Systems (retired)
                    Port Washington WI USA
                    [email protected]
                    http://www.talsystems.com

                    Comment


                    • #11
                      Take out the calls to the command interpreter by using the provided intrinsic functions and I'll bet it will be even smoother and faster.
                      Sorry if I'm being thick Micheal but which intrinsic functions? The command interpreter is needed because the app never knows what response is going to come back from the instrument. OK, it should be a reply to the latest request for data, status or whatever but that's by no means guaranteed. Each received message comes back as:

                      STX, Command, NumBytes, Data, Checksum, ETX

                      and the command interpreter takes the Data and displays it with regard the the Command.

                      Am I missing something? Wouldn't be the first (nor the last) time!

                      John

                      Comment


                      • #12
                        When you say "command interpreter" I am thinking "SHELL" to CMD.EXE.

                        Then again, "code not shown."
                        Michael Mattias
                        Tal Systems (retired)
                        Port Washington WI USA
                        [email protected]
                        http://www.talsystems.com

                        Comment

                        Working...
                        X