C5.5 to C10 Conversion

I’m converting my C5.5 apps to C10 and am having problems that appear to be thread related. I have one screen that uses the Browse Template to read a file. The first time in, everything works just fine. The next time I open the screen, nothing displays. In debugging the app, the codes gets “Record not Available” doing the Next() on the View the second time the screen is opened. The only way to get it to work again is to close and reopen the app. However if I use START to open the screen (that is, open it in a new thread), it works every time. Why does this make a difference? I have hundreds of windows that do this sort of thing and I hate to think I have to re-code all my apps; and in a lot of cases, I want them to close windows before opening another window which using START does not restrict them from doing this.

Thanks for any help anyone can give.

Check out your table and view open/closes to make sure you’re not leaving anything to an implicit closing. When you open a table or view, the scope is at the THREAD level, even if the view is declared at the PROCEDURE level.

So if you exit a procedure without closing the view(s) contained within that procedure, those view(s) won’t be closed automatically (unless the thread itself is closed). Next time in, your procedure won’t be able to open the view because it’s already open.

Not sure if that’s your problem, but that’s what bit me once.

The is the generated code that Resets the View. As you can see, it initially closes the view
BRW1::Reset ROUTINE
!|
!| This routine is used to reset the VIEW used by the BrowseBox.
!|
! Start of “BrowseReset ROUTINE, before setting range limit values”
! [Priority 5000]

! End of “BrowseReset ROUTINE, before setting range limit values”
IF NOT BRW1::ActiveInvisible THEN
IF NOT ?List{PROP:Visible} THEN
BRW1::LoadPending = True
EXIT
END
END
BRW1::LoadPending = False
CLOSE(BRW1::View:Browse)
CASE BRW1::SortOrder

The first time in, the CLOSE(BRW1::View:Browse) generates a File Not Open error which is expected because it has not been opened. The next time in this error is not generated so the View must not have been closed. So I put a CLOSE(BRW1::View:Browse) in the procedure just before the files are closed. This made no difference. The view is not being closed even though I specifically closed it. Is there a way to FLUSH all opened Views/Files?

Other than testing for errors in strategic places and making sure your opens/closes are matched up, (and ruling out other procedure calls stepping on your toes), I don’t know what else to suggest.

If you remain stuck, maybe post the generated module(s) in question and maybe someone will notice something.

It gets even more strange. The only way I could get this to work was to close the View and then close and reopen the file the View was over. But when I did this, it ended up closing the file in another procedure which was opened in another thread. This screen and others had no problem under C5.5.

This app has a DLL that contains all the files and exports them and then all the executables have all the files declared as external. Do you think this could have anything to do with the weird behavior?

Thanks,

Marie

That sounds like your files are global NON threaded. Check the dct and make sure the Threaded box is checked on all tables. It’s rare to have an unthreaded table.

what Sean said - I was about to suggest the same but he has beaten me to it…

another way to check is in the generated code for the file declarations make sure you have ,THREAD on the declaration

cheers

Geoff R

All files are threaded.

Have you also recompiled your global DLL recently (in concert with the other DLLs)?

Just a thought.

Yes, I’ve recompiled it several times.

Maybe another set of eyes would catch something in your code? I have seen nothing like what you describe.

Y’all have missed the key point here. This program is all running on one thread. Main menu procedure, every browse, every form - all on thread 1. So ,THREAD in dict or not is irrelevant.

Leaving aside the significant problems with this model for starters, it does at least mean all the code is “thread safe” because it’s all on thread 1.

The root of the problem is that because it’s all on 1 thread, all global data (which is usually THREADed - and hence cleared at the start of each thread) is always in scope, and is not cleaned up between calls to the procedure.

So to answer the first question, you need to find out what is not being “cleaned up” by the browse correctly when it is closed. My guess is it will be related to some embed code or filter or something like that.

But what about this part?
It gets even more strange. The only way I could get this to work was to close the View and then close and reopen the file the View was over. But when I did this, it ended up closing the file in another procedure which was opened in another thread. This screen and others had no problem under C5.5.

Attached is the procedure that is having the problem. Hopefully someone can see something in it.
code.zip (20.9 KB)

Thanks,
Marie

Have you tried a CLOSE(BRW1::View:Browse) before closing the files?

Is this window always called via a START’d procedure (or by START)? If so, is there a reason you don’t have MDI turned on and MODAL turned on? I think MODAL is deprecated. Not sure if it would introduce other probs.

The CLOSE() before setting the view order seems counterintuitive to me. That’s generated code?

Thanks Jeff. I have tried the Close(BRW1::View:Browse) before closing the files and that made no difference.

If the procedure is called via START then it works all the time. If it is not called via START, then it only works the first time the procedure is called. As for MDI, it causes problem if the procedure is not called via START so I just left it off. I can set it as long as I open it via START.

The reason I don’t want to have to start this procedure via the START command, is that the users can go and do other functions without closing this window which I don’t want them to do.

Marie

Yes. That is generated by the Browse Template. I agree, it doesn’t make a lot of sense. However when I debug this procedure (and it was not activated by START), the first time in the Close() generates a File Not Open error (which is expected). But the next times in there is no error generated.

In the procedure that’s CALLING the PhysicalInv procedure (or any other procedure that uses that same thread), do you do anything with the files in question? Do you open or close any of those tables without altering their corresponding “Used” counter variables? such as ID::Used, etc.

Your original posts mentions “Record Not Available” error. So maybe we went down a wrong rabbithole
with the state of the open() anyway.

Would be interesting to know what STATUS(ID) would return at that point though. Unfortunately, STATUS(View) doesn’t work.

Does the filename/owner change in your app?

PhysicalInv is being called from the Main procedure and Main doesn’t open any files except a configuration and security file. When I start the application, the only thing I’m doing is opening PhysicalInv so I know no other procedure is opening the ID database.

I mentioned the “Record Not Available” error because that is the error I get when a Next() is performed on the View the second time PhysicalInv is opened.

The Filename/Owner never changes once the application is initialized.

I put a Status(ID) in the BRW1::Reset Procedure (see below) and it returns 66 (Read/Write + Denynone) in all cases.

BRW1::Reset ROUTINE

IF NOT BRW1::ActiveInvisible THEN

** IF NOT** ?List{PROP:Visible} THEN

** ** BRW1::LoadPending = True

** ** EXIT

END

END

** ** BRW1::LoadPending = False

** ** CLOSE(BRW1::View:Browse)

CASE BRW1::SortOrder

OF 1

** ** IF BRW1::UsingAdditionalSortOrder THEN

** ** BRW1::UsingAdditionalSortOrder = False

** ** BRW1::View:Browse{PROP:Order} = '+UPPER(ID:id_id)'

** ** END

** ** SET(ID:key_id)

OF 2

** ** IF BRW1::UsingAdditionalSortOrder THEN

** ** BRW1::UsingAdditionalSortOrder = False

** ** BRW1::View:Browse{PROP:Order} = '+UPPER(ID:id_altno),+UPPER(ID:id_id)'

** ** END

** ** SET(ID:Key_Altno)

OF 3

** ** IF BRW1::UsingAdditionalSortOrder THEN

** ** BRW1::UsingAdditionalSortOrder = False

** ** BRW1::View:Browse{PROP:Order} = '+UPPER(ID:id_mfgno),+UPPER(ID:id_id)'

** ** END

** ** SET(ID:Key_MFG_No)

OF 4

** ** IF BRW1::UsingAdditionalSortOrder THEN

** ** BRW1::UsingAdditionalSortOrder = False

** ** BRW1::View:Browse{PROP:Order} = '+UPPER(ID:id_class),+UPPER(ID:id_typ),+UPPER(ID:id_id)'

** ** END

** ** SET(ID:Key_class)

OF 5

** ** IF BRW1::UsingAdditionalSortOrder THEN

** ** BRW1::UsingAdditionalSortOrder = False

** ** BRW1::View:Browse{PROP:Order} = '+UPPER(ID:id_id)'

** ** END

** ** SET(ID:key_id)

END

IF ERRORCODE()

**StandardWarning**(Warn:ViewOpenError)

END

** ** OPEN(BRW1::View:Browse)

IF ERRORCODE()

**StandardWarning**(Warn:ViewOpenError)

END

IF Message(Status(id)) Then .

SET(BRW1::View:Browse)