AutoHotkey Community

It is currently May 27th, 2012, 1:11 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 7 posts ] 
Author Message
 Post subject: Question about CRITICAL
PostPosted: January 6th, 2010, 8:45 pm 
Offline

Joined: September 28th, 2007, 3:56 am
Posts: 279
Location: New York
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


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 7th, 2010, 3:43 am 
Offline

Joined: February 2nd, 2008, 4:35 am
Posts: 643
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
}


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 7th, 2010, 1:41 pm 
Offline

Joined: September 28th, 2007, 3:56 am
Posts: 279
Location: New York
I didn't think of that I'll give it a shot, should work, thanks a ton.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 7th, 2010, 10:08 pm 
Offline

Joined: September 28th, 2007, 3:56 am
Posts: 279
Location: New York
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 8th, 2010, 2:14 pm 
Offline

Joined: September 28th, 2007, 3:56 am
Posts: 279
Location: New York
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 9th, 2010, 2:39 am 
Offline

Joined: January 5th, 2008, 12:11 am
Posts: 102
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).


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 10th, 2010, 5:51 am 
Offline

Joined: February 2nd, 2008, 4:35 am
Posts: 643
Here you go... (tested) :D
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--
}


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: Leef_me, Ohnitiel and 14 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group