2016年7月23日土曜日

DoEventsとはなにか

DoEventsとは何でしょうか。DoEventsが何をするかということは
プログラミング初心者にとっては非常にわかりづらいものです。
私もVBAを始めたばかりのころはDoEventssがなんなのかわからなかったですし
これが何なのかわかったのはスレッドを勉強してからです。

スレッドがなんなのかわかっている人にはDoEventsが何なのかすぐわかると思います。
これは擬似的にマルチスレッド(っぽいもの)を実現するためのもの、、、と理解すればいいでしょう。

例えば以下のコードを見ます。

Sub test()
Dim i As Long
Dim j As Long

For i = 0 To 100000
  j = i
  If i = j Then
    Range("A1") = i
  End If
Next

MsgBox ("終了")

End Sub

これはIとjの数を0から100000までひたすら比較するプログラムです。
「比較する」という行為は重い行為なので、これを実行すると終了までものすごく時間が掛かります(コードを実行する際には注意!!)。
しかも、実行が終わるまでの間、画面が白くなってしまって一切の操作を受け付けません。問題はここで、処理が長いだけならまだしも処理をしている間他の操作が一切できないのはユーザーにとって不便すぎるのです。ユーザーはこの長い処理をやっぱり中断ししようとしたり処理中に他の作業を進めたりしたい場合もあるでしょう。

これを解決するのがDoEventsです。このコードの途中にDoEventsを入れてみます。

Sub test()
Dim i As Long
Dim j As Long

For i = 0 To 100000
  j = i
  If i = j Then
    Range("A1") = i
  End If
  DoEvents 
Next

MsgBox ("終了")

End Sub

すると、今度はプログラム実行中にも関わらず画面が白くならず、画面を操作できることがわかります。

でも、DoEventsは新たなスレッドを作っているわけではありません。
DoEventsは「発生したイベントがオペレーティングシステムによって処理されるように制御を戻す」ための関数です。

DoEventsがないと、もちろんCPUは一つの処理のみをします。本来CPUが処理できる仕事はひとつだけだからです。
するとCPUはこの処理が終了するまで一切の他の処理をしません。
もしこの処理が時間のかかるものである場合、ユーザーはかなりの時間何もせずに待つことになります。

(時間のかかる処理A)


しかし、For loopにDoEventsを挟むことで、CPUは(時間のかかる処理A)と(その他の処理)を高速・交互に処理するようになります。

(時間のかかる処理A)←→(ユーザーの操作受付)

すると、本来CPUは一度にひとつのことしかできないにもかかわず、CPUが処理を交互に高速に実行することで
まるで2つの処理を同時に実行しているかのように見せることができるのです(つまり擬似的なマルチスレッド)。