時間待機ですが、VB6.0なのでこちらに変更しました。
いろいろ、試行してるのですが、良いコードの書き方がわかりません。
for i = 0 to 10
for k = 0 to 10
str_Adreess = fncGetAddress(k,i) 'アドレス取得
call wbbrowser.Navigate(str_Adreess)
’10秒待機
next k
next i
この10秒待機をCPU率を上げないで実装したいです。
Document_Complite で サクサク進むじゃなくて、
10秒待ちたいのです。
ループだと駄目なんですよね
タイマーも使えないし。。。
下記では如何ですか?
http://hanatyan.sakura.ne.jp/
「逆引きヘルプ一覧表」上から2/3辺りの
プログラムの実行を一定時間停止する(API関数使用)
他のフォームで作業をしてるので Sleep は使えません。
バッチやスクリプトとは異なりますので、イベントドリブンにしてください。
Private mi As Long, mk As Long
Private Sub AutoNavigate()
mi = 0&
mk = 0&
Call WebBrowser1.Navigate(fncGetAddress(mk,mi))
mk = 1&
Timer1.Interval = 10000
Timer1.Enabled = True
End Sub
Private Sub Timer1_Timer()
Call WebBrowser1.Navigate(fncGetAddress(mk,mi))
mk = mk + 1&
If 10& < mk Then
mk = 0&
mi = mi + 1&
If 10& < mi Then
mi = 0&
Timer1.Enabled = False
End If
End If
End Sub
DoEvents命令を使用すれば、タイマーに処理がわたると思います。
Declare Function SleepEx Lib "kernel32.dll" _
(ByVal dwMillsecounds As Long, ByVal bAlertable As Long) As Long
for i = 1 to 100
call SleepEx(100,false)
DoEvents
next i
過去ログにいいのがありますのでそれを読んでみてください。
http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi?print+200502/05020047.txt
それはそれとして、
待機ループの中でSleepとDoEventsを繰り返し使うのは適切でないとよく言われます。
そりゃもうMSより信頼できる魔界の仮面弁士さまやK.J.K.さまといったVIPの方々がそういう発言をしているので間違いありません。(ぇ
Sleepの弊害としては待機中にイベントが無視されるということがあります。
たとえば、デスクトップ上の全てのアプリに対して再描画指令が出たときに待機中だったならウィンドウの表示が愉快なことになったりしますよね。
DoEventsの弊害としてはメッセージキューに溜まったものだけ処理してくれればいいのですが、同じイベントが不必要に何度も発生してしまう危険があります。
たとえば、SocketコントロールのDataArrivalイベントでもってデータを読み出している最中にDoEventsを呼ぶと、もうひとつDataArrivalイベントが発生したりするらしいです。
(わたしはやったことがありませんが)
なんにせよDoEventsの使用は必要最小限にしたほうがいいということだね。
ということで、MSが勧めるMsgWaitForMultipleObjects APIを使用して、sleepを使わない(CPU負荷低)かつ必要最小限なDoEvents呼び出しの待機関数 WaitIdolTime を作って見ました。
' 起動時間を取得
Private Declare Function timeGetTime Lib "winmm.dll" () As Long
Private Const MaxTime = 2 ^ 32 - 1
' メッセージ待機
Private Declare Function MsgWaitForMultipleObjects Lib "user32.dll" ( _
Optional ByVal Count As Long = 0&, Optional ByVal HandlesPointer As Long = 0&, _
Optional ByVal WaitAll As Long = 0&, Optional ByVal Milliseconds As Long = 0&, _
Optional ByVal WakeMask As Long = &HFF&) As Long
Public Sub WaitIdolTime(ByVal msec As Long)
Dim BeginCount As Long
Dim NowCount As Long
Dim Interval As Long
If msec <= 0 Then msec = 1
BeginCount = TimeGetTime() ' 現在カウント
Interval = msec
Do
' イベント発生か時間経過まで待機
If MsgWaitForMultipleObjects(, , , Interval) = 0 Then DoEvents
' 待機中イベント発生後の残待機時間
Interval = msec + BeginCount - NowCount
Loop While (Interval >= 0&)
End Sub
もっとも、このままでは49.7日後と24.9日後にトンでもないことがおきる可能性があるので、(わたしは)このままでは使う気になりません。
ま、それは先ほど挙げた過去ログで解決されていることですが。
と、まぁ、質問タイトルにそのまま答えればこの通りでいいのですが、
K.J.K.さまが
>バッチやスクリプトとは異なりますので、イベントドリブンにしてください。
とおっしゃっているとおり、今回の件ではタイマーイベントにすべきだと思います。
例えば時間待機関数で待つとしたら、質問者の案ではこのような関数になるとします。
Private Sub AutoNavigate2()
Dim i As Long, k As Long
for i = 0 to 10
for k = 0 to 10
Call WebBrowser.Navigate(fncGetAddress(k,i))
Call WaitIdolTime(10000) ' 10秒待機
next k
next i
End Sub
これをボタンクリックで呼び出すとしたらこうなります。
Private Sub Command1_Click()
Call AutoNavigate2()
' Call AutoNavigate() ' K.J.K.さまのサンプルを呼び出す場合
End Sub
イベントドリブンでもボタンクリックイベントに書くコードは一緒です。
AutoNavigate2に全てまとまっているか、
AutoNavigateとTimer1_Timerに分割されているかだけの違いになりますね。
それこそタイマーの名前を変えてしまえば、
Private Sub timAutoNavigate_Timer()
と出来るので、違和感は無いと思いますよ。
ツイート | ![]() |