AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Question about CRITICAL

 
Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
ribbs2521



Joined: 28 Sep 2007
Posts: 273
Location: New York

PostPosted: Wed Jan 06, 2010 7:45 pm    Post subject: Question about CRITICAL Reply with quote

I have a function which queries data from a MySQL database. If you try to run a second query without "closing" the first you will get a "command out of sync" error from MySQL. The "closing" occurrs at the end of the function so, since I'm getting these errors this tells me that this function is being run more than once at a time. I need to ensure that this function is never run more than once at any given time. I need to ensure that each time it is run, if finishes before it is run again. I put critical in the function but I still get the commands out of sync.

The problem, I believe, lies in that I have a sub routine which queries data every 60 seconds on a timer. There are also actions to various gui components that call queries so when a user clicks a gui action, if it happens to be at the same time the timed sub is running it causes this issue. I can't really post code because the code is over 80 pages. Honestly the code isn't what I'm initially concerned with, it's how I can stop a function from running parallel.

Am I misunderstanding Critical
Am I putting Critical in the wrong place
or is Critical not my solution and if so, what ideas do you have
Back to top
View user's profile Send private message
a_h_k



Joined: 02 Feb 2008
Posts: 627

PostPosted: Thu Jan 07, 2010 2:43 am    Post subject: Reply with quote

How about something like this...

Code:
;(within subroutine which queries data every 60 seconds on a timer)
While (InQuery = 1) {
}  ; Wait for Query() to finish before calling again
Query()


;(user clicks a gui action)
While (InQuery = 1) {
}  ; Wait for Query() to finish before calling again
Query()


Query()
{
global InQuery
InQuery = 1

(...)

InQuery = 0
}
Back to top
View user's profile Send private message Visit poster's website
ribbs2521



Joined: 28 Sep 2007
Posts: 273
Location: New York

PostPosted: Thu Jan 07, 2010 12:41 pm    Post subject: Reply with quote

I didn't think of that I'll give it a shot, should work, thanks a ton.
Back to top
View user's profile Send private message
ribbs2521



Joined: 28 Sep 2007
Posts: 273
Location: New York

PostPosted: Thu Jan 07, 2010 9:08 pm    Post subject: Reply with quote

OK, so, some wierd stuff happens here, I'll try to explain.

Basically, if I leave the While loop empty, it never completes the first call to that function. Here is what happens

10 seconds....
gonna run and inQuery is ><
Query In Process (From the Timed Call)
Ran Timed Routine
wait 1 second
I press F4
Query In Process (From the F4 call)
....wait for timed routine to run again....
gonna run and inQuery is >1<
wait 1 second
Click OK

then nothing happens... when I opened the debugger it shows it looping in the timed routine's while loop.


Here is the code
Code:
SetTimer, TimedRoutine, 10000


F4::
  While (inQuery) {
  }
  querytest()
  msgbox, inQuery is >%inQuery%<
  return


TimedRoutine:
  msgbox, gonna run and inQuery is >%inQuery%<
  While (inQuery) {
  }
  querytest()
  msgbox, Ran Timed Routine
  return


querytest()
{
  global inQuery

  inQuery := 1
  Msgbox, Query In Process
  inQuery := 0

}


The wierdest part is that if I put return in the while loop everything works fine, as soon as I click OK from the F4 call, the timed subroutine starts going again. I originally had the while loop in the beginning of the function but took it out in case that was the reason but got the same results.

That's the code I used just to test that method so you can test it too if you want.
Back to top
View user's profile Send private message
ribbs2521



Joined: 28 Sep 2007
Posts: 273
Location: New York

PostPosted: Fri Jan 08, 2010 1:14 pm    Post subject: Reply with quote

I think it's because It's looking at different memory addresses. If AHK is like other languages then each time you change the value or size of the variable the address is going to change. So, I think it may be looping waiting for the wrong memory address to change and it's not so it's stuck in a continuous loop.

I'm not sure it's possible but maybe that's what is going on, that's the only thing I can think of at this point.
Back to top
View user's profile Send private message
Kellianjaxon



Joined: 04 Jan 2008
Posts: 102

PostPosted: Sat Jan 09, 2010 1:39 am    Post subject: Reply with quote

No, actually the problem has to do with thread priorities. Because TimedRoutine thread interrupts F4 hotkey thread and they have equal priorities, the hotkey thread never gets to carry on execution until TimedRoutine finishes (which it doesn't do in the code example).
Back to top
View user's profile Send private message
a_h_k



Joined: 02 Feb 2008
Posts: 627

PostPosted: Sun Jan 10, 2010 4:51 am    Post subject: Reply with quote

Here you go... (tested) Very Happy
Code:
SetTimer, TimedRoutine, 10000
queueNum = 0

Loop
{
  tooltip  %inQuery% ----- %queueNum%:  %queue1% - %queue2% - %queue3% - %queue4%

  While (inQuery) {        ;Wait till inQuery() not running
    Sleep, 10              ;So don't hog cpu
  }

  While (!queueNum) {      ;Wait for queue to have item/s
    Sleep, 10
  }

  If (queue1 = "F4")
  {
    querytest()                    ;Have main "F4" code here now
    msgbox,,, Ran F4, 1
  }
  Else If (queue1 = "TR")
  {
    querytest()                    ;Have main "TimedRoutine" code here now
    msgbox,,, Ran TimedRoutine, 1
  }
}

F4::                      ;Quick IN/OUT routine now  (to avoid priority/interruption issues)
  queueNum++
  queue%queueNum% = F4
  tooltip  %inQuery% ----- %queueNum%:  %queue1% - %queue2% - %queue3% - %queue4%
  return

TimedRoutine:              ;Quick...
  queueNum++
  queue%queueNum% = TR
  tooltip  %inQuery% ----- %queueNum%:  %queue1% - %queue2% - %queue3% - %queue4%
  return

querytest()
{
  global
  inQuery := 1
  tooltip  %inQuery% ----- %queueNum%:  %queue1% - %queue2% - %queue3% - %queue4%
  Msgbox, Query In Process
  RemoveFirst()
  inQuery := 0
  tooltip  %inQuery% ----- %queueNum%:  %queue1% - %queue2% - %queue3% - %queue4%
}

RemoveFirst()
{
  Global
  Loop, %queueNum%      ;Shift queue items left by 1  (FIFO; #1 = top of queue)
  {
    next := A_Index + 1
    queue%A_Index% := queue%next%   
  }
  queueNum--
}
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group