VBA の DoEventsに対する考察
DoEventsとは
長年その意味が良くわからなかったのがDoEventsです。
DoEvents 関数 (Visual Basic for Applications) | Microsoft Learn
MicrosoftのTimer関数のサンプルコードでは、ループの合間にDoEvents が実行されています。
DoEvents ' Yield to other processes.
Loop
タイマー関数 (Visual Basic for Applications) | Microsoft Learn
これ、何のために実行してるの? と思い、今回改めて調べてみました。とても参考になったのは次のページです。
なるほど、DoEventsを実行すると、Excelに対して発生していたイベントをExcelに処理させることができるんですね。
ノンプリエンプティブなマルチタスクOS
そこで疑問に思ったのは、上のコードに書かれていたYield to other processes.というコメントです。
他のプロセスにゆずる、と書かれているけど、他のプロセス(Edgeなど)は、そんなことしなくても処理を続行できるのでは?、と思いました。
そして思い出したのは、Windows 3.1など、いにしえのノンプリエンプティブなマルチタスクOSです。
Windows 3.1 系統(95, 98, Me等)のOSは、OSがExcel等のアプリにCPUの使用権を渡すと、アプリが使用権を自発的に返すまで待つという仕組みでした。これだとアプリが使用権を返さないと、他のアプリはもちろん、OSまで停止してしまいます。
実際、昔のWindowsだと、Windowsごとフリーズして、再起動するしかないという事がしばしば起きました。
それに対して、Windows NT系のOS(2000, XP, 7, 8, 10, 11)は、アプリ等の実行時間をOSが管理していて、アプリを強制的に停止して、他のアプリやOSを動かす仕組みです。これだとExcelがマクロを実行中でも、他のアプリ等も実行可能です。
ノンプリエンプティブOSにおけるDoEventsは、Excelにイベントを実行させる、というよりは、むしろOSに制御を返すのが本来の目的だったのかもしれませんし、レファレンスの記述もそうなっています。
DoEventsはできるだけ使わない方がいい?
DoEventsを使うと、マクロを実行しながらExcelの操作ができるという良い面もあるけれど、Excelを操作できてしまうため、不整合を引き起こす原因にもなりかねません。
例えば、A1セルを参照しながら計算処理をするマクロを実行中に、A1セルの値を書き換えてしまったら当然計算は破綻します。
また、リファレンスには、イベントプロシージャー実行中の問題も書かれています。
それを考えると DoEventsはむやみに使わない方が良いのではないかと思っています。
なお、DoEventsを使う事により、応答なしを回避したり、長時間のプロシージャー実行をキャンセルしたりできるようです。
応答なしを回避する例:
時間がかかる処理での「応答なし」を回避するには?:.NET TIPS - @IT (itmedia.co.jp)
キャンセルの例:
コメント
コメントを投稿