Access (VBA)

Access VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 10 Pro : Microsoft 365)
非同期処理を実装したい
投稿日時: 23/11/22 09:38:38
投稿者: tsusasu

おはようございます。
 
非同期処理を実装したくネット検索して作成してみました。
正常動作しますが処理が並列でなく直列になります。
 
※メインサブそれぞれ30秒程度かかる簡単なループ作業をさせて、
 ともに結果が出るまでの時間を測ったら60秒って出てしまいました。(何度も試しています)
 
そもそもの話として、AccessVBAでの非同期処理は実装不可なのでしょうか?
他案やヒントなどをいただければありがたいです。
 
よろしくお願いいたします。
 
※コード簡略化のため、コンスト/デストラクタ、エラートラップ、コメントなどは削除してます。
 
 
'■Mdl_AsyncMain(標準モジュール:非同期開始&メイン処理)
 
Option Compare Database
Option Explicit
 
Private p_clsAsyncNotify As New Cls_AsyncNotify
 
Public Sub AsynchronousMain()
 
    p_clsAsyncNotify.StartAsynchronous
     
    '--- メイン処理記述 ---
     
    Debug.Print "メイン処理実行結果 : "
     
End Sub
 
 
'■Mdl_AsyncSub(標準モジュール:サブ処理)
 
Option Compare Database
Option Explicit
 
Private p_lngTimerID As Long
Private p_clsAsyncEvent As Cls_AsyncEvent
 
Private Declare Function SetTimer Lib "User32" (ByVal hWnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "User32" (ByVal hWnd As Long, ByVal nIDEvent As Long) As Long
 
Public Sub CreateTimer(ByRef clsTimer As Cls_AsyncEvent)
 
    Set p_clsAsyncEvent = clsTimer
        p_lngTimerID = SetTimer(Application.hWndAccessApp, 1, 1000, AddressOf AsynchronousSub)
     
End Sub
 
Private Sub AsynchronousSub()
 
    Dim lngRet As Long
 
    lngRet = KillTimer(Application.hWndAccessApp, p_lngTimerID)
     
    '--- サブ処理記述 ---
     
    p_clsAsyncEvent.NotifyEvent 999
     
End Sub
 
 
'■Cls_AsyncEvent(クラスモジュール:サブ受取&イベント発生)
 
Option Compare Database
Option Explicit
 
Event Notify(ByVal lngRet As Long)
 
Public Sub BeginAsynchronous()
 
    Call CreateTimer(Me)
 
End Sub
 
Public Sub NotifyEvent(ByVal lngRet As Long)
 
    RaiseEvent Notify(lngRet)
 
End Sub
 
 
'■Cls_AsyncNotify(クラスモジュール:イベント検知)
 
Option Compare Database
Option Explicit
 
Private WithEvents p_clsAsyncEvent As Cls_AsyncEvent
 
Public Sub StartAsynchronous()
 
    Set p_clsAsyncEvent = New Cls_AsyncEvent
        p_clsAsyncEvent.BeginAsynchronous
     
End Sub
 
Private Sub p_clsAsyncEvent_Notify(ByVal lngRet As Long)
 
    Debug.Print "サブ処理実行結果 : " & lngRet
     
End Sub

回答
投稿日時: 23/11/23 14:35:36
投稿者: hatena
投稿者のウェブサイトに移動

VBA単体では並列処理に対応していません。
 
裏技的な方法としてVBSを呼び出すとか、別アプリケーションを起動して処理するとか、あるようです。
 
下記はExcelでの実装例です。これをAccess用に書き換えて実装できるかもしれません。
 
Excelブック単体でExcelVBAを疑似マルチスレッド化してみる - えくせるちゅんちゅん
https://www.excel-chunchun.com/entry/2019/03/27/005233
 
クラスとイベントとマルチプロセス並列処理|VBA技術解説
https://excel-ubara.com/vba_class/VBA_CLASS_06.html

投稿日時: 23/11/27 08:50:05
投稿者: tsusasu

hatena様
 
おはようございます。
ご回答どうもありがとうございます。
参考サイトのご紹介もありがとうございます!
 
クライアントでメイン処理とイベント検知、
.NETのActiveXExeでサブ処理をサーバの位置付けにして動かしたら並列処理になりました。
(※本当はAccessVBAだけで完結したいと思っています)
 
DAOのRecordsetOptionEnumクラス、dbRunAsyncメンバー(定数)を使用しているサイトもありましたが、
レコードセットオープン時など限定的な非同期処理っぽいので、実践投入しようか迷っています。
 
勉強になりました。
どうもありがとうございました!