App installieren
How to install the app on iOS
Follow along with the video below to see how to install our site as a web app on your home screen.
Anmerkung: This feature may not be available in some browsers.
Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden.
Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Parallelisierung mit MS-Access VBA
- Ersteller flybyray
- Erstellt am
flybyray
Vice Admiral Special
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
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
- 7.468
- Renomée
- 293
- Standort
- Aachen
- 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
Vice Admiral Special
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.
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.
- Mitglied seit
- 16.11.2001
- Beiträge
- 21.666
- Renomée
- 1.249
- Standort
- München
- Aktuelle Projekte
- World Community Grid
- Lieblingsprojekt
- Folding@Home
- Meine Systeme
- AMD Ryzen 9 5950X
- BOINC-Statistiken
- Folding@Home-Statistiken
- Prozessor
- AMD Ryzen 9 5950X
- Mainboard
- ASUS TUF Gaming X570-Pro [WI-FI]
- Kühlung
- be quiet! Shadow Rock 3
- Speicher
- 4x 16GB DDR4-3200 Corsair Vengeance LPX
- Grafikprozessor
- ASRock Radeon RX 550 Phantom Gaming Aktiv 2GB
- Display
- LG 27UL850-W, 27"
- SSD
- Samsung 980 PRO 2TB, Samsung 840 EVO 500GB
- HDD
- Seagate Barracuda 7200.14 3TB SATA3
- Optisches Laufwerk
- Samsung SH-S183A SATA schwarz (im externen Gehäuse)
- Gehäuse
- be quiet! Silent Base 802 schwarz
- Netzteil
- be quiet! Straight Power 11 Platinum 550W
- Tastatur
- Logitech G613 Lightspeed
- Maus
- Logitech M510
- Betriebssystem
- Ubuntu Linux 22.04
- Webbrowser
- Vivaldi
- 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...
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
Vice Admiral Special
TiKU vielen dank für die Nachfrage.
siehe: The CreateThread API Revisited
Ich habe mal auf dem Code vom Appleman herumgehackt und diesen in eine Access-VBA Umgebung verwendet:
Module1:
Klassenmodul "clsBackground":
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.
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.
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.VBA kann man nicht zu nativem Code kompilieren, es ist immer interpretiert, richtig?
Ja das mag ein Problem sein ich habe, dabei auf die Funktion CoInitialize gehofft.Gerade dann dürfte die Initialisierung der Runtime schwierig werden, da sie ja als Interpreter bei jedem einzelnen Befehl benötigt wird.
Code:
Declare Function CoInitialize Lib "ole32.dll" (ByVal pvReserved As Long) As Long
...
res = CoInitialize(0)
Ja ich denke das ist machbar nur wird es eben nicht viel bringen, da der auszuführende Code tatsächlich in VBA vorliegt.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.
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.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...
Ich habe mal auf dem Code vom Appleman herumgehackt und diesen in eine Access-VBA Umgebung verwendet:
Module1:
Code:
Option Compare Database
Option Explicit
' Structure to hold IDispatch GUID
Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(7) As Byte
End Type
Public IID_IDispatch As GUID
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 'For 32 Bit Systems
Declare Function DllGetClassObject Lib "ole32.dll" (riid As GUID, rclsid As Long) As Long
Declare Function CoGetPSClsid Lib "ole32.dll" (riid As GUID, pClsid As Long) As Long
Declare Function CoRegisterPSClsid Lib "ole32.dll" (riid As GUID, rclsid As Long) As Long
Declare Function CoMarshalInterThreadInterfaceInStream Lib "ole32.dll" (riid As GUID, ByVal pUnk As IUnknown, ppStm As Long) As Long
Declare Function CoGetInterfaceAndReleaseStream Lib "ole32.dll" (ByVal pStm As Long, riid As GUID, pUnk As IUnknown) As Long
Declare Function CoInitialize Lib "ole32.dll" (ByVal pvReserved As Long) As Long
Declare Sub CoUninitialize Lib "ole32.dll" ()
Declare Function CreateThread Lib "kernel32" (ByVal lpSecurityAttributes As Long, ByVal dwStackSize As Long, ByVal lpStartAddress As Long, ByVal lpParameter As Long, ByVal dwCreationFlags As Long, lpThreadId As Long) As Long
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Public Function test()
Dim a As clsBackground
Set a = New clsBackground
StartBackgroundThreadApt a
End Function
' Start the background thread for this object
' using the apartment model
' Returns zero on error
Public Function StartBackgroundThreadApt(ByVal qobj As clsBackground)
Dim threadid As Long
Dim hnd&, res&
Dim threadparam As Long
Dim tobj As ISimpleObj
Set tobj = qobj
' Proper marshaled approach
InitializeIID
res = CoMarshalInterThreadInterfaceInStream(IID_IDispatch, qobj, threadparam)
If res <> 0 Then
StartBackgroundThreadApt = 0
Exit Function
End If
hnd = CreateThread(0, 2000, AddressOf BackgroundFuncApt, threadparam, 0, threadid)
If hnd = 0 Then
' Return with zero (error)
Exit Function
End If
' We don't need the thread handle
CloseHandle hnd
StartBackgroundThreadApt = threadid
End Function
' Initialize the GUID structure
Private Sub InitializeIID()
Static Initialized As Boolean
If Initialized Then Exit Sub
With IID_IDispatch
.Data1 = &H20424
.Data2 = 0
.Data3 = 0
.Data4(0) = &HC0
.Data4(7) = &H46
End With
Initialized = True
End Sub
' A correctly marshaled apartment model callback.
' This is the correct approach, though slower.
Public Function BackgroundFuncApt(ByVal param As Long) As Long
Dim qobj As Object
Dim qobj2 As clsBackground
Dim res&
' This new thread is a new apartment, we must
' initialize OLE for this apartment
' (VB doesn't seem to do it)
res = CoInitialize(0)
' Proper apartment modeled approach
res = CoGetInterfaceAndReleaseStream(param, IID_IDispatch, qobj)
Set qobj2 = qobj
'Do While Not qobj2.ISimpleObj_huba
'Loop
' qobj2.ShowAForm
' Alternatively, you can put a wait function here,
' then call the qobj function when the wait is satisfied
' All calls to CoInitialize must be balanced
CoUninitialize
End Function
Code:
' Class clsBackground
' MTDemo 3 Multithreading example
' Copyright © 1997 by Desaware Inc. All Rights Reserved
Implements ISimpleObj
Option Explicit
Event DoneCounting()
Dim l As Long
Public Sub ISimpleObj_huba()
MsgBox "huba"
End Sub
Public Function ISimpleObj_DoTheCount(finalval As Long) As Boolean
Dim s As String
Debug.Print finalval
If l = 0 Then
' s$ = "In Thread " & App.threadid
' Call MessageBox(0, s$, "", 0)
End If
l = l + 1
If l >= finalval Then
l = 0
ISimpleObj_DoTheCount = True
Call MsgBox(0, "Done with counting", "", 0)
RaiseEvent DoneCounting
End If
End Function
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)
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.
Ähnliche Themen
- Antworten
- 0
- Aufrufe
- 52K
- Antworten
- 29
- Aufrufe
- 13K
- Antworten
- 0
- Aufrufe
- 143K
- Antworten
- 0
- Aufrufe
- 134K
- Antworten
- 3K
- Aufrufe
- 603K