Results 1 to 15 of 15
  1. #1
    twgonder is offline Expert
    Windows 10 Access 2021
    Join Date
    Jun 2022
    Location
    Colombia
    Posts
    565

    How to keep global variables from being stomped on by NEW instance or other form?

    I started thinking how I'm going to port part of an old design to Access, which allows for more than one process to run in a "workspace".

    I'm not sure I've got the thinking correct on this, or if there is a way to avoid what I'm thinking might happen.

    Trying to make it simple:

    F1 = form 1
    F2 = form 1 as a new instance or a completely different form

    CM1 = class module for the form F1 which has procedures
    CM2 = class module for the form F2 which has procedures

    GV1 = global variable 1

    SP1 = supporting procedure 1

    I've got an array of global variables that I use for passing parameters between supporting procedures. This is because sometimes a sub is too complicated with multiple values to send or pass back (thus avoiding a function), or there may be a few different procedures that run before the final procedure needs the global variable that was calculated in a previous procedure.

    In my old db system, if one started a new process (like a form), its workspace (and all variables) was completely isolated from the one that spawned it.

    I'm wondering now what will happen in this example with Access:

    F1 starts and and a procedure in CM1 uses SP1 to set GV1, F1 now waits for the user to do something.


    F2 starts and and a procedure in CM2 also uses SP1 to set GV1, but it has a different value for GV1 than what was set for F1. F2 now waits for the user to do something.

    F1 starts to run again, but in GV1 the value is what was needed for F2 and is invalid for F1.

    Normally I'm used to a string of procedures running uninterrupted from start to finish without the possibility of another proces "getting in the way".

    Is there a way around this in Access? In most cases I expect that a form's procedures will run from start to finish for most things, but it's possible that a waiting textbox entry could allow another procedure to run and contaminate global variables.

    The routine I have is a lot more complicated than described above (with saving and restoring global variables when there is more than one level of SPn being called), but no matter how complicated it is, the same basic problem could arise. I use .Hwnd in forms, but this problem isn't limited to only forms, so the only way around it, that I can see is something like .Hwnd, for uniquely identifying any procedure that might run.

  2. #2
    Minty is offline VIP
    Windows 10 Office 365
    Join Date
    Sep 2017
    Location
    UK - Wiltshire
    Posts
    2,799
    In my opinion if more than one process can set the same Global and have different consequences, it's no longer suitable for use as a Global, it should be a form level variable, then you don't have an issue as it remains tied to that instance of the form.
    I'm also not sure how you think another process is going to change that variable, Access is not Asynchronous, only one routine or event is ever running at once, and in the order you determine (to a large degree).

    Can you demonstrate otherwise?
    DLookup Syntax and others http://access.mvps.org/access/general/gen0018.htm
    Please use the star below the post to say thanks if we have helped !
    ↓↓ It's down here ↓↓

  3. #3
    twgonder is offline Expert
    Windows 10 Access 2021
    Join Date
    Jun 2022
    Location
    Colombia
    Posts
    565

    A picture to explain

    Okay, so after hours of revisiting this ancient problem, I decided to make a hand-drawing (my apologies, I'm not a graphic artist nor great with paint programs.)
    This is a situation that can happen in any computing environment that isn't top-down or thread independant.
    The explanation below the image:

    Click image for larger version. 

Name:	2023.01.29Global1.jpg 
Views:	23 
Size:	57.7 KB 
ID:	49577

    P1 is a program, it can be a form, report, update; any code that runs in any environment, not just Access or VBA.
    P2 is the same or another program.
    P3 is another program that P1 and P2 both call to get a result. The result doesn't lend itself to a simple function return of one value.
    It's not important what these programs do, just think in general terms of programs, processes or whatever terminology you are used to.
    However, at the end I'll explain the bugger that happens in Access, let's just get through the general flow first.
    The numer at the start of each arrow shows the respective order of each call.

    Each program has subroutines, however you want to think or call them.
    Both P1 and P2 have two subroutines. Subroutine S1 in each calls S1 in P3, which returns a global variable (I'll explain why a global in a moment).

    Both P1 and P2 need to pass the global variable to their respective S2.

    NOW, for the practical (but made super simple for demonstration purposes) of the bugger in Access

    Suppose that both P1 and P2 have the same textbox, and this textbox calls before and after update.
    Let's say we want to allow the user to enter a decimal number 0-255 and we want to store in the record the actual hex value, so there is a conversion that has to be done in S1 of P3 (it changes 255 to FF for example).

    The BeforeUpdate does this conversion, but Access won't allow it to be written to the record, that has to be done by the AfterUpdate procedure. Since we have no control over the arguments in BeforeUpdate or AfterUpdate, we have to rely on some kind of global variables to pass the hex value.

    If step 5 completes before step 6 for some reason, then we have the hex value for P2 in P1.

    In step 4 the GV stomps on what is needed in step 6.
    I see two ways (maybe there are more) to handle this, but I'm not sure how in Access.
    1. You've got to make step 6 "modal" somehow so that step 5 can't run first.
    2. There has to be a way to localize the GV in steps 5 and 6 (which yes, Access can do in a given module, but the nature of event oriented programming causes another iteration of the same problem, just in a different level.)

    One can add layers and layers of complexity to the problem (I have in tests), but it always comes back to the same basic issue of some global variable being contaminated by the possibility of multiple threads running in the same workspace.

    Anyone got an idea how to make this work?

  4. #4
    twgonder is offline Expert
    Windows 10 Access 2021
    Join Date
    Jun 2022
    Location
    Colombia
    Posts
    565

    Minty, maybe...

    Quote Originally Posted by Minty View Post
    In my opinion if more than one process can set the same Global and have different consequences, it's no longer suitable for use as a Global, it should be a form level variable, then you don't have an issue as it remains tied to that instance of the form.
    I'm also not sure how you think another process is going to change that variable, Access is not Asynchronous, only one routine or event is ever running at once, and in the order you determine (to a large degree).

    Can you demonstrate otherwise?
    Okey, this is my third attempt to write something legible to your post.

    I'm with you, up to a point. Trying to figure out if Access isn't "asynchronous" (to me meaning multiple program threads run at one time) in code execution, then I'm wondering how to get two instances of the debugger showing at once to see this in action? (Or you and I are talking apples and oranges).

    I may have been lazy up to this point in using a global array to pass variables within and between modules. It makes sense to have two such arrays, one for global (when calling between modules) and one for the module (dim in the declarations section of the module) for passing within the module (like the before and after update problem {link below]). It's a little bit more work and I have to be very careful to where I'm calling a procedure (module or global).

    For this to work, I would (maybe) need to copy the module array (from a second level sub) to the global array when calling a sub/function from another module (happens a lot as I have modules for dates, strings, numbers, etc.) and then copy global array back to the module array (kind of like passing arguments, but some of my arrays for passing have dozens of values, hence using the array--I think it may have been you, Minty, who saw one of these samples in a different thread and went WTF!!!?). Also, no other procedure could touch the global variable while all this copying and executing is happening.

    Further, for this to work, then Access has to be, by my definition, completely asynchronous (like old RS232 communications, one bit at a time, and even old top-down programs). Even with this, is there the possibility that before a textbox (or any control) is finished with all its calling procedures that another textbox (or control or procedure) could get focus and mess up the module variable? if so, then we're back to square one.

    Finally, I've been playing with NEW and creating instances of the same form running multiple instances of a form at the same time (Microsoft Access tips: Managing Multiple Instances of a Form (allenbrowne.com). I've got to investigate further, but several times it appears that closing or resetting one instance has contaminated variables in another instance. I'm not sure if there is something special that has to be done to eliminate this happening, but it's somewhat related here as there can be not-so-logical-contamination to module/global variables from other instances.

    If you're wondering how it came to all of this, here's kinda where it started: https://www.accessforums.net/showthr...688#post505688

  5. #5
    Minty is offline VIP
    Windows 10 Office 365
    Join Date
    Sep 2017
    Location
    UK - Wiltshire
    Posts
    2,799
    If you reset the code anywhere it will destroy any global variables.

    Access is (as far as I am aware) completely asynchronous within it's own application space. Only one form, and/or module or class and it's events are actively processed at any given time.
    It is intrinsically an Event driven application.

    In you example 1 above you state that both P1 and P2 share the same textbox, but the net result is that isn't possible, you can only instigate one process at a time, so you might call either P1 or P2, or P1 then P2, but you can't call them at the same time.
    Last edited by Minty; 01-30-2023 at 03:19 AM.
    DLookup Syntax and others http://access.mvps.org/access/general/gen0018.htm
    Please use the star below the post to say thanks if we have helped !
    ↓↓ It's down here ↓↓

  6. #6
    Minty is offline VIP
    Windows 10 Office 365
    Join Date
    Sep 2017
    Location
    UK - Wiltshire
    Posts
    2,799
    DP - but this might link might help:
    https://www.reddit.com/r/vba/comment.../async_in_vba/
    DLookup Syntax and others http://access.mvps.org/access/general/gen0018.htm
    Please use the star below the post to say thanks if we have helped !
    ↓↓ It's down here ↓↓

  7. #7
    twgonder is offline Expert
    Windows 10 Access 2021
    Join Date
    Jun 2022
    Location
    Colombia
    Posts
    565
    Here is an example, if we're talking about the same thing, of P1 (MyForm2_3) running two instances at the same time.
    Click image for larger version. 

Name:	230124Search.jpg 
Views:	19 
Size:	179.9 KB 
ID:	49579

  8. #8
    Minty is offline VIP
    Windows 10 Office 365
    Join Date
    Sep 2017
    Location
    UK - Wiltshire
    Posts
    2,799
    I understand having multiple instances of a form.
    My point was that no matter how many forms you have open you are only running code in one of them at any given time.

    And I can see no point whatsoever in assigning values to Globals that might be used in multiple instances of those forms. You wouldn't do that in any other programming language why would you think it would work in Access?
    That's just poor design. You might pass a value into a form on the open event, but then you would assign it to a form local variable so it doesn't get lost if another event somewhere might change it.

    Personally, Globals should only be used for things that can't go out of scope, and then you can just set then as a self healing property.
    Using tonnes of globals sounds like band-aid for a poor design with lots of possible rabbit holes to fall down.
    DLookup Syntax and others http://access.mvps.org/access/general/gen0018.htm
    Please use the star below the post to say thanks if we have helped !
    ↓↓ It's down here ↓↓

  9. #9
    twgonder is offline Expert
    Windows 10 Access 2021
    Join Date
    Jun 2022
    Location
    Colombia
    Posts
    565

    Trying to explain better

    Quote Originally Posted by Minty View Post
    ... You wouldn't do that in any other programming language why would you think it would work in Access?...
    Okay, I'll try again with another diagram and new explanation because we aren't talking about passing variables to a form when it opens. Although search forms do pass the WHERE value to a form well into the form's processing.

    Let's assume that my old design didn't work, even though it did for 35+ years.
    (In the example below, it would work because (2) couldn't run before (3) because it wasn't "event-driven".)
    So, how would we do this in Access? It models a real-world db that uses BeforeUpdate, AfterUpdate, Form_Error, validate and replace procedures (in a mind-boggling manner due to the way Access wants to order and permit what its procedures can do).

    First, see the legend at the top of the attached image.

    P1 and P3 are form class modules that the form F1 calls.
    P2, P4, P5, P6 can be procedures found in a module(s) that isn't the Form class module, that is to say they are generalized code that are used by multiple forms (Fn), reports and updates found in different modules that often call each other or operate in a recursive manner.

    For the sake of argument, imagine v (value) as just one module/global variable, but in reality, it is a module/global array depending on which procedure is being called (my first analysis was that a global v might work because a module scoped variable runs into the same problem eventually).
    v3 and v6 need to be stored for later use by P5 and P6 which then update textboxes (or other controls) in F1.
    v3 and v6 don't get passed back to the form, they remain in a variable that doesn't lose scope (whatever you want to call it, module or global).

    Imagine, as stated before that F1 can jump around between dozens of procedures, as well as multiple Fn can run and do their own jumping about with tabs (clicks, returns) that the user can do in any conceivable order (unless we resort to the unseemly tactic of making controls active line-by-line).

    How can we get v3 passed to P5 even though P4 changed the module/global variable to v6?

    I started testing ported and modified old-code to store the different values (v) with a signature (but multiple forms all working in the same workspace buggered this all up by duplicating signatures), but I'm wondering if there isn't a simpler way in Access that I've just not seen yet. I figure there must be a way, as I can't be the first person to write prescriptive, post-entry and validation logic more advanced than the Access entry and error messages allow for.

    This is the second time I've heard about "self healing properties", could you please give a hint how to learn about that?

    Thanks


    Click image for larger version. 

Name:	2023.01.29Global2.jpg 
Views:	20 
Size:	77.1 KB 
ID:	49581

  10. #10
    orange's Avatar
    orange is offline Moderator
    Windows 10 Office 365
    Join Date
    Sep 2009
    Location
    Ottawa, Ontario, Canada; West Palm Beach FL
    Posts
    16,647
    I don't know how relevant this is, but I recall a youtube video by Juan Soto re Spawning multiple instances of a form. It might be worth watching if only for familiarity.

    Also, I am not an active user of class modules, but the concept of a Form(class) withEvents that would react/sink another form's event (whatever would involve your second..third..form) could be a path worth investigating.

    Others on the forum are familiar with Classes and WithEvents and may have more advice.

    A Pillai has a series of tutorials on his website.

  11. #11
    twgonder is offline Expert
    Windows 10 Access 2021
    Join Date
    Jun 2022
    Location
    Colombia
    Posts
    565

    Synchronous

    I'm not quite sure what you mean when you say Access is synchronous. Here's a basic definition that I've seen applied to many types of natural and electronic conversations.

    Click image for larger version. 

Name:	2023.01.29Global3.jpg 
Views:	21 
Size:	56.6 KB 
ID:	49584

    By this definition, I would say Access is quite asynchronous in that both a form and its class procedures can't run at the same time. However, the procedure can change the form appearance, so that part appears synchronous. Hard to say.
    Simultaneous processing of multi-threaded logic is not something I think Access can do, and if it can, I want to see it in the debugger (I've got an idea how to test that by opening F1 then sleeping it while F2 opens and does some code and see if that code continues while a programmed focus reverts back to F1, the kind of sleep makes a difference I suppose--when I have a half hour.)


    When it came to RS232 and and parrallel printer communication, "synchronous" often (erroneously) meant there was a clocking signal involved for multi-stream control.

  12. #12
    twgonder is offline Expert
    Windows 10 Access 2021
    Join Date
    Jun 2022
    Location
    Colombia
    Posts
    565
    When I say form class procedures, I mean the things in the highlighted area on top of the image.

    Click image for larger version. 

Name:	2023.01.29Global4.jpg 
Views:	21 
Size:	30.5 KB 
ID:	49585

    Both links look good, thanks.

  13. #13
    moke123's Avatar
    moke123 is online now Me.Dirty=True
    Windows 11 Office 365
    Join Date
    Oct 2012
    Posts
    1,499
    There's another category for class modules

    Click image for larger version. 

Name:	cls.png 
Views:	23 
Size:	3.1 KB 
ID:	49586

    When I say form class procedures, I mean the things in the highlighted area on top of the image.
    I generally refer to form modules as form modules, modules as standard modules and custom class modules as class modules.

    Form modules are technically class modules but I differentiate between the two as I use a lot of custom classes.
    If this helped, please click the star * at the bottom left and add to my reputation- Thanks

  14. #14
    Minty is offline VIP
    Windows 10 Office 365
    Join Date
    Sep 2017
    Location
    UK - Wiltshire
    Posts
    2,799
    Quote Originally Posted by twgonder View Post
    I'm not quite sure what you mean when you say Access is synchronous.
    Typo - sorry. I've corrected my original post.
    DLookup Syntax and others http://access.mvps.org/access/general/gen0018.htm
    Please use the star below the post to say thanks if we have helped !
    ↓↓ It's down here ↓↓

  15. #15
    moke123's Avatar
    moke123 is online now Me.Dirty=True
    Windows 11 Office 365
    Join Date
    Oct 2012
    Posts
    1,499
    Quote Originally Posted by orange View Post
    I don't know how relevant this is, but I recall a youtube video by Juan Soto re Spawning multiple instances of a form. It might be worth watching if only for familiarity.

    Also, I am not an active user of class modules, but the concept of a Form(class) withEvents that would react/sink another form's event (whatever would involve your second..third..form) could be a path worth investigating.

    Others on the forum are familiar with Classes and WithEvents and may have more advice.

    A Pillai has a series of tutorials on his website.
    I wouldn't doubt that custom classes would be the way to go with much of the things that TWG is trying to do.
    Custom events, form instances, etc.
    If this helped, please click the star * at the bottom left and add to my reputation- Thanks

Please reply to this thread with any new information or opinions.

Similar Threads

  1. Global Variables
    By Homegrownandy in forum Programming
    Replies: 4
    Last Post: 09-03-2018, 06:23 AM
  2. VBA is reseting all my global variables...
    By ohmydatabase in forum Access
    Replies: 7
    Last Post: 10-14-2017, 03:02 AM
  3. Replies: 8
    Last Post: 10-08-2014, 06:08 PM
  4. Cannot create Global Variables
    By Paul H in forum Programming
    Replies: 3
    Last Post: 05-20-2014, 11:27 AM
  5. Global Variables?
    By futurezach in forum Reports
    Replies: 4
    Last Post: 06-20-2013, 03:45 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Other Forums: Microsoft Office Forums