DLL with callback problem (1 Viewer)

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 13:10
Joined
Feb 28, 2001
Messages
26,999
I don't know how to make a COM component.

I have not seen anything on that topic either. Sorry I can't offer you anything useful.
 

sonic8

AWF VIP
Local time
Today, 19:10
Joined
Oct 27, 2015
Messages
998
The problem is how can I use this code to a separate thread with a callback to vba that uses UI elements of MS Access Form without crash. I had just removed the details not to mislead someone.


(As mentioned before, my knowledge of C/C++ is limited to almost nothing.)
So, as it appears, there is no (simple) mechanism in C/C++ to invoke a method on another thread.



If I had to make things work the way you want them to be, I would ...

  • Create and open a hidden form in Access,
  • Pass the forms window handle into your C/C++ method,
  • Subclass the the form's window proc in the DLL code,
  • (maybe, instead of the previous 3 steps, just create a window in the DLL)
  • Start your worker threads,
  • If any worker thread wants to raise an event, it posts a message to the forms message queue,
  • The form's window proc handles the message and invokes the callback function.
I guess, this is how updating the UI is supposed to work in a multi threading environment, unless there are more sophisticated mechanisms available.

Please note, using a window message queue is polling by design, as is the example you posted.
 

sonic8

AWF VIP
Local time
Today, 19:10
Joined
Oct 27, 2015
Messages
998
The topic of multithreading with VBA was on my list for quite a while.This thread finally pushed me to record a video on that topic. - It's not really a solution to the issues raised here, but it covers several sidelines touched by this this thread.

So, I think is justified to post a link here:Multithreading with VBA?
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 13:10
Joined
Feb 28, 2001
Messages
26,999
Watched the video. One issue stood out. The difference between hard compile and pseudo-code compile is razor thin from the compiler viewpoint but not even close from the execution viewpoint. VBA does not produce executable code.

https://analystcave.com/vba-compiler-add-in-to-vb-net/

VBA pseudo-compiles code but since it is not Intel "86" family code, it cannot be executed in the strict sense of just putting the starting address in the hardware PC register (the ultimate GOTO). It can only be processed by a pseudo-code simulator, emulator, or interpreter depending on the specifics. (And yes, those three methods ARE different.) I don't claim to know which of those three options actually applies in the case of VBA, but speed tests clearly show that loops are not true-executed. They are pseudo-executed. This is the basis for many claims about the preference for running SQL vs. VBA, because at least SQL's underlying code is true-compiled. A recordset loop, though it has to do essentially a similar thing, isn't true-compiled.

The VBA execution environment is processing the instructions in sequence. If a hardware interrupt occurs, it occurs in the VBA processor's code and the address to which the interrupt returns would be inside the VBA processor, not the pseudo-code. It is interesting that as long as you don't leave the raw computational environment, you can parallel-process stuff like strings - probably because the string paradigms are re-entrant. I suspect this is because the O/S also uses the string library and thus it would HAVE to be re-entrant to be worth a damn. And I have no idea how it knows that you have pseudo-code as the target of your AddressOf in the CreateThread call. But apparently it does.

The video is absolutely correct that you can write true-compiled .DLL code to be RE-ENTRANT (thus able to be called from multiple threads in parallel). If you don't write it re-entrantly, you can trip over your own feet, usually due to the "improperly shared resource" issue. This ties in with a discussion I held a long time ago about whether VBA was truly object-oriented. You point out that if you diddle with an object, things go south quickly. That implies that the COM objects were not written re-entrantly and thus are not fully object-oriented either. I'm going out on a limb here to say that part of the problem is that you don't get a new copy of the code for NEW class object methods. If you did, the code would indeed be re-entrant. Instead, I think the Access environment shares the same compiled code among all instantiations of the same class. THIS IS A GUESS based on observed behavior!

It is equally interesting that you can write recursive code in VBA as long as you only use locally defined variables inside the routine - because all of the local variables go on the program stack in a context block. Recursive code is necessarily also re-entrant.

By the way, the reason for having issues with your earlier code in a 2016 environment might be explained in this article:

https://docs.microsoft.com/en-us/of...64-bit-visual-basic-for-applications-overview

Something has changed between then and now, probably related to the difference between 32-bit and 64-bit code. Is there a chance that your original code was Ac2007, not Ac2010? Because it appears that the code compatibility change occurred with the release of Ac2010.
 

sonic8

AWF VIP
Local time
Today, 19:10
Joined
Oct 27, 2015
Messages
998
@The_Doc_Man: Thank you very much for these insights and valuable additional information.

I've got the gut feeling that you missed something in your remarks regarding pseudo-code and the implications of the VBA runtime executing the code instead of the code itself being executable. - I cannot put the finger to it. I have to admit; my knowledge of these low-level mechanisms is insufficient to discuss these matters.

I'm going out on a limb here to say that part of the problem is that you don't get a new copy of the code for NEW class object methods. If you did, the code would indeed be re-entrant.
No, that is not the case. Class instances are isolated from each other and the code of class modules is re-entrant (if you wrote it that way). It works to use multiple class instances in a single threaded environment, and it works as well with multiple instances in a multithreaded environment. I said in the video that you shouldn’t touch classes because that significantly increases the risk of Access/VBA crashing, but not because the instances aren’t isolated/re-entrant in general.

Something has changed between then and now, probably related to the difference between 32-bit and 64-bit code. Is there a chance that your original code was Ac2007, not Ac2010?
No chance whatsoever. I actually wrote the code in Access 2016 originally and noticed that it was crashing left, right, and centre. I was about to scrap the whole project when I ran the code in Access 2010 and noticed it runs there without crashing.
 

Users who are viewing this thread

Top Bottom