Parallelisierung mit MS-Access VBA

flybyray

Commodore Special
★ Themenstarter ★
Mitglied seit
06.06.2008
Beiträge
416
Renomée
9
Standort
München
System
Details zu meinem Desktop
Ist Parallelisierung in MS-Access VBA mit Hilfe von Threads durch COM+ möglich?
Die meisten Stimmen im Internet sagen generell, dass Parallelisierung unmöglich ist und wenn man mein Lösungen zu finden dann stellt sich heraus das die Lösung externe Prozesse sind. Externe Prozesse sind aber keine wirkliche Lösung, da man ja hier IPC (Interprocess Kommunikation) betreiben muss um Daten auszutauschen oder Berechnungen im Kontext eines bestehenden Prozesses durchführen zu können.

Daher hier meine Fragen:
Wird der MS-Access VBA Code selbst in der Runtime in einem sogenannten "Single-Threaded Apartments" (STA) Modell ausgeführt?

Wenn ja:
Könnte man mit Hilfe CoMarshalInterThreadInterfaceInStream , CoGetInterfaceAndReleaseStream (siehe Abschnitt "Marshaling Interface Pointers Between Apartments" InsideCOM+) COM Komponenten (plural) schreiben als Erweiterung um mit Hilfe der Interfaces Berechnungen im VBA Kontext anzustoßen und zwar in eigenen Threads?

Hoffentlich ist mein Anliegen verständlich. Ich selbst bin mehr Java Entwickler, aber habe immer Interesse auch mal am "Tellerand" auftrende Probleme zu lösen. Nur bei der Sache wäre es mir echt recht wenn da jemand mit Erfahrung und Ahnung vielleicht mal was sagen könnte oder hinweise geben könnte. Vielen Dank
 

BoMbY

Grand Admiral Special
Mitglied seit
22.11.2001
Beiträge
4.998
Renomée
244
Standort
Aachen
System
Details zu meinem Desktop
Prozessor
Ryzen 3700X
Mainboard
Gigabyte X570 Aorus Elite
Kühlung
Noctua NH-U12A
Speicher
2x16 GB, G.Skill F4-3200C14D-32GVK @ 3600 16-16-16-32-48-1T
Grafikprozessor
RX 5700 XTX
Display
Samsung CHG70, 32", 2560x1440@144Hz, FreeSync2
SSD
AORUS NVMe Gen4 SSD 2TB, Samsung 960 EVO 1TB, Samsung 840 EVO 1TB, Samsung 850 EVO 512GB
Optisches Laufwerk
Sony BD-5300S-0B (eSATA)
Gehäuse
Phanteks Evolv ATX
Netzteil
Enermax Platimax D.F. 750W
Betriebssystem
Windows 10
Webbrowser
Firefox
Was genau soll den parallelisiert werden? Wäre es nicht vielleicht sinnvoller aus der Access-Anwendung eine .NET Anwendung zu machen?
 

flybyray

Commodore Special
★ Themenstarter ★
Mitglied seit
06.06.2008
Beiträge
416
Renomée
9
Standort
München
System
Details zu meinem Desktop
Ok es braucht noch mehr Background Infos.
Die Anwendung ist schon ziemlich alt und hat eine enorme Quellcode-Basis, die man nicht einfach in absehbarer Zeit umstellen kann.
Der Anwendungskern basiert auf Access 2003 VBA Code. Ein schöne alte Welt von "vor...vorgestern" also. ;D
 

TiKu

Administrator
Teammitglied
Mitglied seit
16.11.2001
Beiträge
14.893
Renomée
890
Standort
Unterföhring
  • SIMAP Race
  • QMC Race
  • Spinhenge ESL
  • Docking@Home
Mein DC
Aktuelle Projekte
Folding@Home
Lieblingsprojekt
Folding@Home
Meine Systeme
Intel Core i7-4771, AMD A10 5700
BOINC-Statistiken
Folding@Home-Statistiken
System
Details zu meinem Desktop
Prozessor
Intel Core i7-4771
Mainboard
ASUS Z87-PRO (C2)
Kühlung
Enermax ETS-T40-TB
Speicher
2x 8GB DDR3-1866 Crucial Ballistix Sport XT
Grafikprozessor
Intel HD Graphics 4600
Display
BenQ FP222WH 1680x1050
SSD
Samsung 840 EVO 500 GB
HDD
Seagate Barracuda 7200.14 3TB SATA3
Optisches Laufwerk
Samsung SH-S183A SATA schwarz
Gehäuse
BitFenix Shinobi schwarz
Netzteil
be quiet! E9-400W
Tastatur
Logitech MK300
Maus
Logitech M510
Betriebssystem
Windows 7 Professional x64 SP1, Linux Mint
Webbrowser
Vivaldi
Verschiedenes
Tastatur: Logitech MK300, Maus: Logitech M510
Internetanbindung
▼100 MBit ▲40 MBit
In Sachen MultiThreading besteht bei VB und vermutlich auch bei VBA ein Problem darin, die Runtime für den neuen Thread zu initialisieren. VBA kann man nicht zu nativem Code kompilieren, es ist immer interpretiert, richtig? Gerade dann dürfte die Initialisierung der Runtime schwierig werden, da sie ja als Interpreter bei jedem einzelnen Befehl benötigt wird.
Was hingegen problemlos geht: Aus VB (und sicher auch VBA) heraus COM-Komponenten verwenden, die z.B. in C++ entwickelt wurden und die intern MultiThreading nutzen.

Was wollt ihr denn parallelisieren? Wenn es reines Numbercrunching ist, könnte eine separate C++-Komponente tatsächlich eine Lösung sein. Wenn der parallelisierte Code auf das Access-Objektmodell zugreifen soll, sollte man sich aber auf jeden Fall erstmal schlau machen, ob dieses Objektmodell threadsafe ist. Nicht dass das intern auf die GUI zugreift und deshalb immer im Kontext des Hauptthreads laufen muss...
 

flybyray

Commodore Special
★ Themenstarter ★
Mitglied seit
06.06.2008
Beiträge
416
Renomée
9
Standort
München
System
Details zu meinem Desktop
TiKU vielen dank für die Nachfrage.
VBA kann man nicht zu nativem Code kompilieren, es ist immer interpretiert, richtig?
Also es gibt eine kompilieren Funktion. Aber es ist wohl richtig, dass es sich dennoch nur um interpretierten Code handelt. Ich denke, dass VBA intern ähnlich wie bei Python die Quellen (*.py) zu binär Code (*.pyc) umwandelt.

Gerade dann dürfte die Initialisierung der Runtime schwierig werden, da sie ja als Interpreter bei jedem einzelnen Befehl benötigt wird.
Ja das mag ein Problem sein ich habe, dabei auf die Funktion CoInitialize gehofft.
Code:
Declare Function CoInitialize Lib "ole32.dll" (ByVal pvReserved As Long) As Long
...
	res = CoInitialize(0)
siehe: The CreateThread API Revisited

Was hingegen problemlos geht: Aus VB (und sicher auch VBA) heraus COM-Komponenten verwenden, die z.B. in C++ entwickelt wurden und die intern MultiThreading nutzen.
Ja ich denke das ist machbar nur wird es eben nicht viel bringen, da der auszuführende Code tatsächlich in VBA vorliegt.

Was wollt ihr denn parallelisieren? Wenn es reines Numbercrunching ist, könnte eine separate C++-Komponente tatsächlich eine Lösung sein. Wenn der parallelisierte Code auf das Access-Objektmodell zugreifen soll, sollte man sich aber auf jeden Fall erstmal schlau machen, ob dieses Objektmodell threadsafe ist. Nicht dass das intern auf die GUI zugreift und deshalb immer im Kontext des Hauptthreads laufen muss...
Es sind tatsächlich eher Rechenroutinen, also Zeitreihen und Prognosen und so Zeug. Teilweise müssen diese sicherlich bereinigt werden. Es ist uralter Code der aber nach wie vor das Berechnet was er soll.

Ich habe mal auf dem Code vom Appleman herumgehackt und diesen in eine Access-VBA Umgebung verwendet:
Module1:
Spoiler
Klassenmodul "clsBackground":
Spoiler
Da man bei der Initialisierung des Threads in VB nur eine COM Componente mit GUID also hier die ProxyStub dll angeben darf. Habe ich noch ein einfaches C++ ATL Projekt mit einem SimpleObj ATL-Objekt erzeugt, das eben ein Interface ISimpleObj deklariert.

Meine Idee war, vielleicht dieses Interface mit VBA Code (Implements ISimpleObj) zu implementieren und dann mit qobj die VBA implementierung für die Thread Initialisierung zu verwenden.
Code:
    res = CoMarshalInterThreadInterfaceInStream(IID_IDispatch, qobj, threadparam)
Leider gibt es dann für res (HRESULT) den Return 0x800A0062 bzw. -2146828190 . Ich vermute das liegt daran, dass die VBA Implementierung Code für Single Appartment Threading enthält und sich so einfach nicht Initialisieren lassen will. Die Bedeutung des Fehlercode ist etwas unbrauchbar an dieser Stelle.

Eine weitere Idee wäre es, falls das überhaupt geht tatsächlich eine C++ COM Komponente zu haben die eine Funktion enthält welche eine Referenz auf ein Interface bekommt. Aber das ist nur herumstochern ohne wirklich Ahnung zu haben was da wirklich vor sich geht wenn man das ganze aus VBA verwenden will. Wäre schön wenn sich das irgendwie debuggen lassen würde.

Möglicherweise muss man sich einfach darauf einlassen mit Teile und Herrsche den alten Code irgendwie zu zerlegen und wichtige Teile auszulagern. Ist nur fraglich wie man das am besten anstellt.
 
Oben