Detect a change in a subform, from the main/parent form (1 Viewer)

moke123

AWF VIP
Local time
Today, 08:05
Joined
Jan 11, 2013
Messages
3,920
I am assuming @moke123 made a typo and meant to do the above.
I was just pointing out the reference was wrong. Thus I said probably and "whatever the reference to the subform is" I was relying on the user to test it.

I had a stupid mistake in my tests. I had to manually set subform's has module property to true.
I mentioned that in post#7. Whenever a WithEvent doesn't work, that is usually the culprit. At least in my case.

I recently added these lines to my MZ-tools code library to keep them handy. I've needed to pass info back to a calling form from pop up forms and run various procedures in the calling form.
Code:
'Dim WithEvents frmCloseEventForm As Access.Form
'Set frmCloseEventForm = Forms("XXX")
'frmCloseEventForm.OnClose = "[Event Procedure]"
'Private Sub frmCloseEventForm_Close()
'End SubOption

The 1st line goes in the declarations obviously.

When I open a form I'll add the next lines like
Code:
Private Sub Command0_Click()

    DoCmd.OpenForm "Form2"

    Set frmCloseEvent = Forms("Form2")
    
    frmCloseEvent.OnClose = "[Event Procedure]"

End Sub

And then a custom event in the calling form

Code:
Private Sub frmCloseEvent_Close()

Me.Text1 = getLBX(frmCloseEvent.List0)

    Set frmCloseEvent = Nothing

End Sub

A quick simple solution with very little coding.
 

moke123

AWF VIP
Local time
Today, 08:05
Joined
Jan 11, 2013
Messages
3,920
Seems that I missed that post. My life would have been much easier if I was a little bit more careful.
I've made that mistake so many times that it's now one of the first things I check.
 

CJ_London

Super Moderator
Staff member
Local time
Today, 13:05
Joined
Feb 19, 2013
Messages
16,613
I regularly apply events to subforms from the main form. Example:

In the main form

Code:
Public Function sfCurrent()'must be public and must be a function
msgbox "record selected in subform"
end function

public function sfCtlWithFocus()'must be public and must be a function
msgbox screen.activecontrol.name & " has focus"
end function

private form_Open() 'depends on what the functions are supposed to do so perhaps use load or current
dim ctl as control
sf.form.oncurrent="=sfCurrent()"
on error resume next ' crude error handling
for each ctl in sf.form.controls
     ctl.ongotfocus="=sfCtlWithFocus()"
next ctl
end sub
unless the subform has it's own requirement for code, you can set the subform hasmodules property to no

The two public functions above could be in a general module if required.

edit: applies to any event - you can pass the form object back using [FORM} as a parameter if required. Only downside is events with parameters such as the mouse and key events - you can still apply a function but won't have access to the parameters. If you don't need them fine, otherwise use a class module which can still be assigned from the main form.
 
Last edited:

sonic8

AWF VIP
Local time
Today, 14:05
Joined
Oct 27, 2015
Messages
998
Please explain.
If I look at a single MsAccess.exe process in a SysInternals Process Explorer or Windows Resource Monitor, it shows between 20 and 40 active threads. Even if I subtract some of those, as they probably were created by add-ins and other satellite components, it is obvious that Access is not a single-threaded application.
2023-02-21_16h38_03.png
 

sonic8

AWF VIP
Local time
Today, 14:05
Joined
Oct 27, 2015
Messages
998
I just happened to see this page from Microsoft a while back.
just as a reference
"The Old New Thing" is an excellent reference for internals of the Windows OS and its APIs!
The external libraries mentioned in that blog post are what I meant by "satellite components".
The thread count I mentioned certainly includes threads that are just active in the sense of "not terminated", but idling along. Still, they are there and waiting for getting work assigned to them.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 07:05
Joined
Feb 28, 2001
Messages
27,186
@sonic8 - Access is single-threaded. Not an assumption. When you do a web search for "Is MSACCESS.EXE multi-threaded" you find out it is not. When you did that Resource Monitor test, is there any chance that you had 26 files open? I don't know what Resource Monitor counts as a thread, but I can tell you that your conclusion is incorrect.

This first link is from the Microsoft Answers forum, from an overseas poster and responder, so the language is a bit rough. I infer that English was not the native language of either participant. However, this is an official MS site that denies that Access supports multiple threads and NOBODY stepped in to correct that statement.


These links also discuss the threading issue. A LOT of people have chimed in among the responders to these threads.




This next link discusses Office single-threading as a matter of design intention. I.e. they were MADE that way. The thread gets a bit techie but clearly indicates that for COM operations (such as are used by Office), MS is using the single-threaded model.


OK, it is possible that I am wrong, too. But I have researched this before. Every one of those threads, from many different sources, seems to emphasize that Access does not use multiple thread techniques in what it does. Basically, fresh-out-of-the-box Access is not multi-threaded. You can call WinAPI entry points to change that, but no native features of Access allow for parallel execution of multiple threads within Access. You HAVE to work at it. In the absence of API calls, Access is fully synchronous.

The last link also explains why even though the ACE (or JET) engines are in a secondary process, they still do not process asynchronously. It is because they are in the same COM "apartment" which is intentionally single-threaded. And it explains why SQL Server's pass-thru queries can be asynchronous. SQL Server is not part of the COM interface group. You use the ODBC style of interfacing, not the COM style.
 

Josef P.

Well-known member
Local time
Today, 14:05
Joined
Feb 2, 2023
Messages
826
Perhaps we should distinguish between msaccess.exe (the development environment) and an application running in Access.

My thoughts on this:
In the case of the development environment, I could imagine that several threads are used. (Why not? msaccess.exe is not written in VB6 ;))
What we create with Access is a synchronously running application. Multithreading requires asynchronous processes. We cannot create these with VBA.
 
Last edited:

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 07:05
Joined
Feb 28, 2001
Messages
27,186
@Josef P. - There is no evidence that multiple threads are affirmatively used at any time during any activation of MSACCESS.EXE - EITHER as the developer environment OR the run-time environment. The application running under control of the run-time environment is interpreting and displaying the data structures of forms and reports, interpreting the table and query defintions, and executing pseudo-code rather than machine code - because VBA does not compile into machine code. That means that the Access run-time environment is still involved, still in control, and still effectively single-threaded.

There ARE threads - as discussed in the Raymond Chen article referenced by KitaYama - created, not necessarily by Access, but perhaps by the file system when opening a DLL-type library or some other file. In that sense, the PROCESS may indeed have allocated some thread structures and not released them. But the program image MSACCESS.EXE doesn't appear to explicitly ask for any more threads.
Perhaps we should distinguish between msaccess.exe (the development environment) and an application running in Access.

I can write some new event code and, without exiting the Access environment, can then open a form and start running my app. Then close that form and modify some code and try it again. All of that without changing one thing about the Windows process/session. So what is there to distinguish?
 

sonic8

AWF VIP
Local time
Today, 14:05
Joined
Oct 27, 2015
Messages
998
When you did that Resource Monitor test, is there any chance that you had 26 files open?
As mentioned, my thread count and the screenshot is from a single MsAccess.exe process and I didn't even open any database at all.

Your statement and my disputing it was about Access, not VBA.
VBA is indeed running a single thread only, unless external components or API's are involved. In regards to VBA you missed the opportunity to quote my own video on multi-threading in VBA to make it appear I contradict myself. - Which I am not, as I strictly refer to Access here in this thread. - Don't let this discussion get multi-threaded. ;-)

As for the remaining links claiming Access being single-threaded ...
I just opened a copy of the Northwind database with 200K records in the Customers table and ran a simple query (SELECT * FROM Customers WHERE [Last Name] > 'A' AND [First Name] LIKE '*X*') using DoCmd.OpenQuery (~3800 results).

I'm not going to bother you with the thread count. Only this much: The single Access (365, V2301) process used 7(!) different CPU cores (of 12 available) while executing that query.
You might argue that the lions share of that work was done by the ACECORE.DLL, which is correct and, if you're splitting hairs, is technically not the MsAccess.exe. Nonetheless, this scenario is similar to those described in the links "proving" Access' singled-threadedness.

Please note: There certainly are queries, which by their design are going to be processed by a single database engine thread only. This might even happen with Microsoft SQL Server. So, I'm not saying the people from those links are misrepresenting facts. I just don't agree with their conclusions.

To wrap things up: You and anybody else feeling inclined to do so can run a similar evaluation on your own computers. I let you arrive at your own conclusions.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 07:05
Joined
Feb 28, 2001
Messages
27,186
I'm not going to bother you with the thread count. Only this much: The single Access (365, V2301) process used 7(!) different CPU cores (of 12 available) while executing that query.

Remember that Windows uses an internal "round-robin" scheduler to speed up context switching and as a way to diminish heat load on any one CPU core. Was that usage seven cores simultaneously or in sequence? I.e. did it just happen to touch seven of the twelve cores before the query was finished? That COULD have been because the query only took seven internal scheduler cycles. Not sure about how long that would be, but if it is even something like 16.66 msec, that is literally 50 million instructions per cycle. AND if it is working fromn a SSD then the disk latency isn't that long either. The query you named only returned 3800 records, which isn't very many.

I used to run an OpenVMS with an 8-thread Longhorn CPU (64-bit) from Intel. I know for an absolute fact that my single-threaded processes nonetheless used multiple cores. And the same guy who wrote the kernel of OpenVMS (Dave Cutler) is ALSO the guy who wrote the security and scheduler kernel of Windows NT - and he explicitly reported that he used VMS software designs for a lot of things. He got away with that because for a while back then, Microsoft and Digital Equipment Corp. had a teaming agreement in which they shared technology. That is also why OpenVMS can run on IBM XEON processors. And that is why the Windows Memory Dynamics almost perfectly match OpenVMS methods.

The problem here is that the Access MAIN code was designed to be single-threaded and to run in a single-threaded environment. As I said, if you use some kind of API, you can multi-thread within VBA. We had someone about three or four years ago who wanted to multi-thread while using WinSock routines as a listener while running other queries and VBA. So I will not say it is at all impossible. I said, and I meant, "fresh out-of-the-box" Access is fully synchronous due to single-threading.

In your video you split hairs regarding VBA being interpreted, emulated, or executed. The correct answer is "emulated" for VBA, "interpreted" for SQL (I think), "executed" for the code in the libraries and MAIN program. I don't dispute the possibility of methods to trigger multi-threading. I don't dispute that you could build your own DLL to go multi-threaded. But that deviates from the question at hand.

In the original post that triggered this diversion, the question came up as to having things happen between parent and child forms. The OP was asking for something that isn't built into Access. Using the API calls to create threads, perhaps he COULD have gotten some level of simultaneity, though I doubt it because of there being TWO forms and because we cannot see the Access portion of form code, only the event code that we write. We can get an event routine to create a program fork, but whether Access would honor it is a totally different question. I'm not sure what would happen if a child form with fork-level code suddenly gets closed with the forked code is still active. I also question what would happen when the forked event code does an Exit Sub while some other form code does a simultaneous Exit Sub. Which thread becomes primary? You pointed out the need to protect threads from each other. I believe that in an emulated environment, that might be more difficult than for a truly compiled environment. (The latter is only a statement of opinion.)

But for either case, the line from the old TV show "The Honeymooners" comes to mind... "Bang, Zoom, straight to the moon." One slip-up in the context of the parallel execution setup and things WILL crash. Your disclaimer at the front of your video IS absolutely correct - this technique is not for production use.
 

AOB

Registered User.
Local time
Today, 13:05
Joined
Sep 26, 2012
Messages
615
Do your children run your household?

I have four daughters, with only 5 years between the oldest and the youngest. You probably want to use a different analogy to get through to me! ;)

(I do take your point...)
 

Users who are viewing this thread

Top Bottom