【テクニカル・上級編】【上級プロ】マルチプロセッサ環境を模倣したバックグラウンド処理:大規模アセンブリのエクスポート中にUIフリーズを防ぐ進捗管理 – SolidWorks VBA解析バイブル

スポンサーリンク

大規模アセンブリを掌握せよ:SolidWorks VBAにおける「ノンブロッキング」進捗管理の極意

SolidWorks APIを扱うエンジニアにとって、大規模アセンブリのバッチ処理は常に「UIフリーズ」という壁との戦いである。`swApp.CommandInProgress = True` を設定し、処理が終わるまでユーザーを放置する時代は終わった。

真のシニアエンジニアは、単に「動くコード」を書くのではなく、OSのイベントループを殺さず、ユーザーの操作性を維持しつつ、堅牢にバックグラウンド処理を模倣する。本稿では、Windows APIとVBAの限界を押し広げる高度な進捗管理術を伝授する。

—

1. なぜVBAでUIフリーズが起きるのか

VBAのシングルスレッド環境において、SolidWorksの重いAPIコール(特に `Mate` の生成や `Export`)は、OSのメッセージキューを完全に停止させる。Windowsは「応答なし」と判断し、描画を諦める。

これを回避する唯一の解は、「処理の細分化」と「メッセージポンプの強制駆動」である。

2. Windows APIによる「生存確認」の実装

`DoEvents` は強力だが、過剰な呼び出しはオーバーヘッドを招く。我々は `PeekMessage` APIを駆使し、最小限のCPU負荷でメッセージを処理しつつ、UIのレスポンスを維持する。

実装:ノンブロッキング・プログレスバーの要諦

以下のモジュールは、大規模アセンブリの処理中にUIを解放するための「心臓部」である。

‘ User32.dllを利用したメッセージポンプの強制駆動
Private Declare PtrSafe Function PeekMessage Lib “user32” Alias “PeekMessageA” _
(lpMsg As Msg, ByVal hwnd As LongPtr, ByVal wMsgFilterMin As Long, _
ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long

Private Type Msg
hwnd As LongPtr
message As Long
wParam As LongPtr
lParam As LongPtr
time As Long
pt As POINTAPI
End Type

‘ UIを更新し、Windowsの「応答なし」を防ぐ
Public Sub KeepAlive()
Dim msg As Msg
‘ メッセージキューに残っているイベントを処理
Do While PeekMessage(msg, 0, 0, 0, 1) <> 0
DoEvents
Loop
End Sub

3. 大規模アセンブリ処理の設計思想

アセンブリを自動作成・合致付けする際、一度に全オブジェクトをメモリにロードしてはならない。SolidWorks APIの `ModelDoc2` は、特定の操作後に必ず「メモリのフラグメント(断片化)」を引き起こす。

メモリを解放する極限のループ処理

Public Sub ProcessLargeAssembly(swApp As SldWorks.SldWorks, assemblyPath As String)
Dim swModel As SldWorks.ModelDoc2
‘ 処理中は必ずDocumentを軽量モード、あるいは必要な構成部品のみロードする

For i = 1 To TotalComponents
‘ 1. 個別の合致処理
AddMateToComponent i

‘ 2. 10回ごとにメモリ最適化とUI更新
If i Mod 10 = 0 Then
‘ オブジェクトの参照を強制的にクリア
DoEvents
KeepAlive ‘ ユーザーの操作を受け付け可能にする

‘ SolidWorksのメモリキャッシュを解放させるための小細工
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swViewDisplayRealView, False
End If
Next i
End Sub

4. チーフアーキテクトの視点:なぜこれが「勝つ」のか

1. メモリの可視化: 多くの開発者は、`Set obj = Nothing` を呼べば解決すると思っている。だがSolidWorks COMラッパーは、`IDispatch` の参照カウントを適切に管理しないと、バックグラウンドでメモリリークを誘発する。ループ内でのオブジェクト生成を最小限にし、再利用可能な `MathUtility` などを活用することが重要だ。
2. プログレスバーの更新頻度: 1フレームごとにプログレスバーを更新するのは無駄だ。タイマー(`QueryPerformanceCounter`)を利用し、最低でも33ms(約30fps)以上の間隔を空けて更新するロジックを組むべきである。
3. レガシー環境への配慮: 64bit環境での `PtrSafe` 宣言は必須だが、古いアドインや他システムとの連携を考えるなら、型変換における `Long` と `LongPtr` の混同を避けるのが最大の保守コスト削減となる。

まとめ:エンジニアの誇り

大規模アセンブリのエクスポートや合致定義は、ただの「自動化」ではない。それは「SolidWorksという巨大なモンスターを、VBAという細い糸で操る」行為だ。

UIがフリーズして「応答なし」と表示されるツールは、プロフェッショナルの現場では「未完成」と同義である。今回紹介した `KeepAlive` の概念を導入し、あなたのツールに「魂の滑らかさ」を実装してほしい。

コードは嘘をつかない。アーキテクチャこそがすべてである。

タイトルとURLをコピーしました