時間待機


kkk  2008-08-18 06:34:23  No: 140224

VBで、ある時間プログラムの進行を止めたいです。

下記のコードだとCPU使用率が100%になってしまいます。
ほかに、方法は無いのでしょうか?

        
Dim Now As Long

        Now = Timer
        While Timer < Now +10     '10秒間待機する
        DoEvents
        Wend
        Beep '終了した事を教える


魔界の仮面弁士  2008-08-18 18:16:07  No: 140225

# VB6 なのですね。
そもそも、「ループでの待機処理」を行うべきではありません。

提示されたコードでは、その他にも、
  ・変数名 Now は、Now 関数と競合する名前なので、避けるべきです。
  ・Timer 関数の戻り値は、Long 型では無い点に注意してください。
  ・10 秒後の値を得るには、DataAdd 関数を使いましょう。
  ・DoEvents は、イベント再入などの弊害を持つので、極力避けましょう。
といった問題があります。

> ほかに、方法は無いのでしょうか?
Timer コントロールを利用しましょう。

Private Sub Command1_Click()
    Timer1.Interval = 10000 '10秒
    Timer1.Enabled = True   '開始
End Sub

Private Sub Timer1_Timer()
    Timer1.Enabled = False
    MsgBox "10秒経ちました。", vbInformation
End Sub

VB のコードは、「イベント」ベースで行われるべきです。
たとえば、チェックボックスの On/Off が行われた時に処理したいなら、
    Do
      DoEvents
      If Check1.Value = vbChecked Then
        Label1.Caption = "On 状態"
      Else
        Label1.Caption = "Off 状態"
      End If
    Loop
のようにループで監視したりはせず、
  Private Sub Check1_Click()
    If Check1.Value = vbChecked Then
      Label1.Caption = "On 状態"
    Else
      Label1.Caption = "Off 状態"
    End If
  End Sub
のように、イベントを用いて処理しますよね。


kkk  2008-08-18 20:25:49  No: 140226

魔界の仮面弁士さん、とても解りやすい指導ありがとうございます。

フォームで作業しながら、見えないところでWebbrowserで巡回しています。

フォームから、タイマーのイベントをtrueにして
Timer1のイベントを発生  そこで、for文で、サイトを巡回します。

Private Sub Timer1_Timer()
    
    Timer1.enabled = false
    
    for i = 0 to x
       Wb.Navigate(address(x))
       
       'ここで10秒待ちたい

       wb.Document.links(0).click

      'ここで10秒待ちたい
       
    next i 

End Sub

'ここで10秒待ちたい  の所に、
検索したループ文で10秒待機しましたが、よくないです。
sleepも駄目。

タイマーを使うと、その先までコードが走ってしまいます。

どうすれば、良いのでしょうか?


我龍院  2008-08-18 23:17:59  No: 140227

タイマーを使用すれば、10秒待って次のイベントを呼び出すことは難しくは無いが、
ループの一番最後の2番目のイベントを呼び出して、CPUの使用率を上げずに
Sleepも使わずに10秒間待つのは難しい............
最後のイベントが終了して待つ必要が無ければ、
Const SEC = 1000
Dim intNo As Integer
Private Sub Command1_Click()
    Timer1.Enabled = False
    Timer1.Interval = 10 * SEC
    intNo = 1
    DoWork
    Timer1.Enabled = True
End Sub
Private Sub Timer1_Timer()
    Timer1.Enabled = False
    intNo = intNo + 1
    DoWork
    If intNo / 2 < 10 Then
        Timer1.Enabled = True
    End If
End Sub
'//何かの処理
Private Sub DoWork()
    If intNo Mod 2 <> 0 Then
        Debug.Print "処理:" & (intNo \ 2) + 1 & "-A"
    Else
        Debug.Print "処理:" & (intNo \ 2) & "-B"
    End If
End Sub
こんな手はある。

ただこんなに苦労しなくても
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function timeGetTime Lib "winmm.dll" () As Long

'待ち時間を1/1000秒で指定
Private Sub timeWait(timeWait As Integer)
    Dim timeStart As Long
    timeStart = timeGetTime
    Dim count As Integer
    Do
        count = count + 1
        If count > 1000 Then
            count = 0
            Sleep (1)
            DoEvents
        End If
    Loop While (timeGetTime <= timeStart + timeWait)
End Sub
こんな関数を一つ作っておけば案外上手くいくかも、CPUの使用率も上がらない。


YuO  2008-08-18 23:57:59  No: 140228

魔界の仮面弁士さんの書かれた,
>> そもそも、「ループでの待機処理」を行うべきではありません。

>> VB のコードは、「イベント」ベースで行われるべきです。
が全てだとおもうのですが。

状態の遷移で考えるようにしてみると,どうすればよいのかわかりやすくなると思います。
「待つ」行為は,「指定時間が経ったら状態が遷移する」のですから,タイマーで十分状態遷移させられます。

> タイマーを使うと、その先までコードが走ってしまいます。

最初の時間待ちは,実はNavigateComplete2イベントを使うべき,ということはありませんか?


魔界の仮面弁士  2008-08-19 00:50:28  No: 140229

>  Wb.Navigate(address(x))
>  'ここで10秒待ちたい
> wb.Document.links(0).click
その処理が、そもそもの間違いであるようにも思えます。

本来は「10秒間待機する」のではなく、ページの読込完後に行うべきなので
リンクのクリック処理を、DocumentComplete イベントに移動しましょう。

ちなみに、NavigateComplete2 は、ページ遷移後に発生するイベント、
DocumentComplete は、HTMLDocument の解析後に発生するイベントです。
Document プロパティへのアクセスを目的とするのであれば、
DocumentComplete イベントの方を使ってみてください。

# フレームを切っている場合、フレーム単位でイベントが発生するので注意。

また、Sleep & DoEvents 法も避けるかと思われます。

VB4 当時の補足ヘルプファイル等で紹介されていた事もあって、未だに
使われている現場を見かけますが、本来 DoEvents する必要が無い時にまで
呼び出される事もあって、イベントよりも負荷率は上です。

そのため、MsgWaitForMultipleObjects を使う、SetWaitableTimer を
併用したりして回避するという手もありますが…標準のイベント処理で
十分に回避できる場合においては、API に頼らず実装した方が安全でしょう。

http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200510/05100129.txt
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200706/07060026.txt
http://support.microsoft.com/kb/231298/ja


kkk  2008-08-19 03:14:07  No: 140230

DocumentComplete を使う方法も知っていますが、

サクサク、リンク移動をしたくないのです。

10秒間隔くらいで推移したい目的があるので

書かれた事をもとに、ロジックを考えて見ます。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加