Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

RLock fails and closes form

Status
Not open for further replies.

sdocker

IS-IT--Management
Aug 12, 2010
218
GB
Hi,

I am using a grid with a CheckBox to change multiple records. I make the changes one at a time, ie. if the user clicks on the CheckBox, the field in the table is REPLACED with the new value.

The problem I'm encountering is if RLOCK fails, it doesn't return .F., It just closes the form.

The form is called as follows:

DO FORM frmMarkExtensions NAME ofrmMarkExtensions LINKED​

Sam
 
What you show and describe doesn't explain, why a failing RLOCK would close your form.

What is your error handling? That means what is ON("ERROR") and what is in the forms Error event (and all parent classes, if there is nothing or dodefault)?

Bye, Olaf.
 
At what point are you testing RLOCK()? What is your code for doing that?

And what do you mean when you say "if RLOCK fails, it doesn't return .F."? In what sense does it "fail", other than returning .F.?

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Actually RLOCK() doesn't even cause any error when you SELECT 0, which means trying to lock the current record in an empty workarea.

The consequence of a closing form has to come from somewhere after the RLOCK. RLOCK by definition returns .t. if it successfully locks ans .F. if not. How you deal with this is up to your code.

Bye, Olaf.
 
Sorry. Obviously it is not as straightforward as I thought.

Here is additional info.
Code:
***********
FUNCTION REC_LOCK
PARAMETERS TRIES
PRIVATE TRY_AGAIN,XMESSAGE

IF RLOCK()
	RETURN (.T.)  && locked
ENDIF

*-* RECORD LOCK FAILED
TRY_AGAIN = TRIES

DO WHILE .T.
	IF RLOCK()
		RETURN (.T.)  && locked
	ELSE
		TRIES = TRIES - 1
		IF TRIES > 0
			INKEY(.1)   && wait 1/10 second
			LOOP
		ELSE
			IF abox( 'RC','I',1,'Could not lock record.', 'Lock Failed on Record # ' + ALLTRIM(STR(RECNO())) ) = 1
				TRIES = TRY_AGAIN
				LOOP
			ELSE
				RETURN(.F.)
			ENDIF
		ENDIF
	ENDIF
ENDDO
RETURN ''
****************


This is in the InterActive method of the CheckBox
Code:
*******
IF REC_lOCK(1)
	     REPLACE CLDATA.OnExt WITH THIS.VALUE
	     REPLACE CLDATA.EXTENDED WITH IIF(THIS.VALUE = 1,'Y','N')
	UNLOCK
ELSE
	abox('OK','?',1,'Lock Failed.','IC')
ENDIF
**********



Code:
PROCEDURE errhand
PARAMETER merror, MESS, Mess1, mProg, mLineNo

lcEMess = abox('RC','I',1, ;
	+ 'Alias: ' + ALIAS() + CHR(13) ;
	+ 'Error number: ' + LTRIM(STR(merror)) + CHR(13) ;
	+ 'Error message: ' + MESS + CHR(13) ;
	+ 'Line of code with error: ' + Mess1 + CHR(13) ;
	+ 'Program with error: ' + mProg + CHR(13) ;
	+ 'Line number of error: ' + LTRIM(STR(mLineNo)), 'Error' )

DO CASE
CASE lcEMess = 1
	RETURN
CASE lcEMess = 2
	IF VERSION(2) = 0  && RUN TIME
		CLEAR EVENTS
		CLEAR ALL
		CLOSE ALL
		QUIT
	ELSE
           	CLEAR EVENTS
		CLEAR ALL
		CLOSE ALL
		QUIT
	ENDIF
ENDCASE


I open the app in another window and select/lock a record. When I try to click the CheckBox of that record. The form closes. No error message. Just back to the TOP LEVEL FORM.

Sam
 
That's helpful. It's now clear what you are trying to achieve.

That said, I can't see any reason for the form to close in the scenario you described. I suspect you have some other code somewhere that is causing the form to close - possibly unrelated to the record locks. You might try searching the form's code (or the entire application) for commands such as RELEASE. Or, run the program in the Trace window to see what's causing the form to close.

Also, your whole approach seems to be heavy-handed. Your Rec_Lock() function appears to be doing exactly the same as SET REPROCESS. Why not simply issue a SET REPROCESS, then just try to lock the record directly? If nothing else, that will simplify the logic, and might help you focus on why the form is closing.

Better still, forget about calling RLOCK(), and use row or table buffering instead.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Why are you returning ''? By the way you never get there. That's in itself bad code, at some level you'd EXIT the loop to return .T. or .F. by default.
What's abox()?

It seems you have some error in that or anywhere else, triggering error handling and triggering clear events, clear all, close all. Like Mike, I don't see any other code that could cause your form to close.
How about using coverage logging to see what happens? In checkbox interactive change you could SET COVERAGE TO somefile.log and then in the end after closing VFP you'll have a log of executed code. That log can be read in via VFP menu_: Tools->Coverage Profile. You can also open it up in notepad and see, whether the last logged lines are the errhand and where you came from.

Bye, Olaf.


 
Thanks Mike,

I'll try your suggestions.

In the meantime, I came across something else unusual.

I have a similar grid that the user uses to select a record/customer to work on. If I try to select a locked record, the Rec_Lock function works. If I then try the problem grid and click on the same record, the lock function now works properly; it returns .F.

Sam
 
Sam,

Regarding that new problem, it might be worth checking that the correct work area is selected. RLOCK() always tries to lock a record in the current work area, unless you pass a parameter to tell it otherwise. If the "wrong" work area is selected, the locking might appear to fail.

But don't get too bogged down with that, at least not for now. Focus first on my earlier suggestions.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Olaf,
Returning '' is a coding error. Though harmless, I will correct it.

I tried invoking the Coverage Profiler and discovered that the InteractiveChange and the Click method were not being triggered at all, by virtue of the fact that the log was not created.

I moved the code to the GotFocus method and it Rec_Lock function works unless I select it two times in succession. The second time it closes the form.
I still haven't figured out why it was working if I tried to lock a locked record from the other grid. (see above).

I think there is something about the sequence of triggered methods that i have to figure out.

Sam
 
Mike,

I checked. The work area never changes. There are no select statements other than to the correct one.

Due to the way the app is engineered, buffering does not seem to be an option, as another user can have the record locked for a long period of time. I think it is more prudent to trap it and notify the user that this particular record is unavailable and cannot be changed at this time.

I will try your suggestion of using the trace window and report back.

Sam
 
>I moved the code to the GotFocus method and it Rec_Lock function works unless I select it two times in succession. The second time it closes the form.

Have you looked into the log yet? It contains every line of code executed in the form of program/class/method and lineno info and Coverage Profiler can show that, or you can read it in via APPEND into a cursor:

Code:
Create Cursor curCoverage (bExecTime B, cClass C(128), cMethod C(128), iLine
I, cFile C(254), iStacklevel I)
Set Point To '.'
Append From coverage.log Type CSV

You'll very obviously see where you come from before the form closes if looking at the last few lines of this.

Bye, Olaf.
 
>REPLACE CLDATA.EXTENDED WITH IIF(THIS.VALUE = 1,'Y','N')

Does this line error? Because your checkbox value might be .F./.T. instead of 0/1.

Bye, Olaf.
 
I also wonder how things go well, if you have bound a filed AND do your own REPLACE statements in Interactive Change. The control will override your REPLACEs, if it takes action through controlsource. And if you haven't set controlsource you have at elast set grid.recordsource, that sets controlsources in all columns automatically.

Bye, Olaf.
 
Besides: Is your FUNCTION REC_LOCK part of a PRG? You can use a prg you SET PROCEDURE to, the called functions will then run in the context of the caller, but it's not OOP, it'll never be obvious you do a function inside a PRG if you call REC_lOCK() somewhere in a form or control method or event.

If you'd put it inside a class definition within a PRG it'll depend on whcih datasession is active when you create a class instance. Then it runs outside of the forms datasession, probably, especially if it's part of a class instanciated in the default datasession and your form runs in a private datasession. That's often an error of novices with putting functions into an application class instanciate as goApp. All these methods will always run in the datasession of instanciating goApp.

You best put such things related to all forms into a base form, then it'll always run in the context of the concrete form datasession, no matter what that is at runtime and you'll call it with THISFORM.REC_LOCK(1)

Bye, Olaf.
 
Olaf,

>REPLACE CLDATA.EXTENDED WITH IIF(THIS.VALUE = 1,'Y','N') - This line is correct. This field was there before I instituted the grid, so I use a parallel field wit 1 or 90 for the checkbox.

I understand that the REPLACE does not belong in the Interactive Change. I moved the code there to see which method gets triggered.

I also figured out why the Rec_Lock function doesn't work two times consecutively. The second time the object still has focus, and GOTFOCUS is nor triggered.

Both the Trace window and Coverage profiler indicate that the code sfor some reasom jumps back to the calling line:

> DO FORM frmMarkExtensions NAME ofrmMarkExtensions LINKED

Sam
 
Olaf,

In answer to your question, "what is ABOX"

It is shareware to facilitate USE of the MESSAGBOX function.

Code:
**********************************************
FUNCTION abox
PARAMETERS boxtype, xicon, DEFBUTT, messtext, ttext
PRIVATE diagtype, retval, maxbutts
IF PARAMETERS()<4
	=MESSAGEBOX("Not enough parameters",16,"ABOX ERROR")
	RETURN 0
ENDIF
IF PARAMETERS()<5
	IF TYPE("_sysname")="U"
		ttext=""
	ELSE
		ttext=_sysname
	ENDIF
ENDIF

DO CASE
CASE UPPER(boxtype)=="OK"
	diagtype=0
	maxbutts=1
CASE UPPER(boxtype)=="OKCAN"
	diagtype=1
	maxbutts=2
CASE UPPER(boxtype)=="ARI"
	diagtype=2
	maxbutts=3
CASE UPPER(boxtype)=="YESNOCAN"
	diagtype=3
	maxbutts=3
CASE UPPER(boxtype)=="YESNO"
	diagtype=4
	maxbutts=2
CASE UPPER(boxtype)=="RC"
	diagtype=5
	maxbutts=2
OTHERWISE
	=MESSAGEBOX("Invalid box type",16,"ABOX ERROR")
	RETURN 0
ENDCASE

DO CASE
CASE UPPER(xicon) = "STOP"
	diagtype=diagtype+16
CASE xicon = "?" .OR. UPPER(xicon) = "Q"
	diagtype=diagtype+32
CASE xicon = "!"
	diagtype=diagtype+48
CASE UPPER(xicon) = "I"
	diagtype=diagtype+64
OTHERWISE
	=MESSAGEBOX("Invalid icon",16,"ABOX ERROR")
	RETURN 0
ENDCASE

DEFBUTT=MIN(DEFBUTT,maxbutts)
diagtype=diagtype+((DEFBUTT-1)*256)
retval=MESSAGEBOX(messtext,diagtype,ttext)
DO CASE
CASE UPPER(boxtype)="ARI"
	retval=retval-2
CASE UPPER(boxtype)="YESNOCAN"
	IF retval=2
		retval=3
	ELSE
		retval=retval-5
	ENDIF
CASE UPPER(boxtype)="YESNO"
	retval=retval-5
CASE UPPER(boxtype)="RC"
	IF retval=4
		retval=1
	ENDIF
ENDCASE
RETURN retval
****************************************

Instructions also attached.
 
 http://files.engineering.com/getfile.aspx?folder=aef8a565-9d5f-40a3-82ea-abc9e4561e29&file=ABOX_-_INSTRUCTIONS.pdf
Well, lookup the meaning of LINKED.

Seems your variable ofrmMarkExtensions goes out of scope and therefore your form finishes. You are linking your form to the existance of the variable.

Bye, Olaf.
 
Both the Trace window and Coverage profiler indicate that the code sfor some reasom jumps back to the calling line:

> DO FORM frmMarkExtensions NAME ofrmMarkExtensions LINKED

It doesn't mean that that line is about to be executed. If frmMarkExtensions is modal, the Trace window is telling you that the application is in a modal state, and is waiting for some interaction from the user. It's exactly the same as if the trace had stopped at READ EVENTS.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Well, indeed Mike is true.

The trace window points at the line executeing, in case of read events or a DO FORM the record pointer can go back there, which doesn't mean this line is reexecuted, it just means there is no further code currently executing and what Mike says is true. The coverage profiler does not show you lines of code in chronological order, it has number of executions, average time etc.

Did you do the append into a cursor? You only see the chronological order of code in that cursor or in the log text file, the coverage profiler will not show you chronological order of code lines executed, but will show the method code and executed lines marked with count and average runtimes, etc.

Only by looking into the raw log or cursor after appending as CSV you find out what executed chronological and last and before you got back to the DO FORM and the lines following after form closing.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top