• 締切済み

Doevents をご教授ください。

VBでシリアルプリンタを制御するアプリケーションを開発しています。 プリンタに状態(ヘッドが開いているとかリボンがないとか)を問い合わせる関数をTimer1_Timer()で呼び出しています。 その関数内、プリンタに問い合わせてからの応答待ちにDo~Loopを使っています。 そのループ内にDoeventsがあります。 プリンタとPCを繋げていると起こらないのですが、繋げてないと、 (1)アプリケーションを終了してもタスクマネージャを覗くとプロセスが残っている (2)デバグしてみるとform.unload()時にTimer1.enabled=falseにしているのにform.unload()が終わるとTimer1.enabled=trueになってしまう (3)(2)の後、Timer1_Timer()に記述したプリンタの状態チェックする関数内のDoeventsに移動して無限ループになってしまう というような現象が起こります。 多分Doeventsの使い方が悪いと思われます。 これを回避する方法を教えてください。

みんなの回答

  • n-before
  • ベストアンサー率50% (3/6)
回答No.2

単純にMSComm1オブジェクトを解放していないために発生しているのではないでしょうか? プログラムを終了するときは MsComm1 = Nothing としないとダメですよ。 おそらく、プリンタと接続されていない場合、 オープンできないのでクローズもできず、オブジェクトを解放できずにいるのではないでしょうか?

leftovers
質問者

お礼

テストしてみましたが、MSCOMM1=Nothingはコンパイルでエラーが起こります。不正なプロパティとか…云々。 でもたぶん貴殿のおっしゃる通りのことだと思います。 これからよく調べてみます。(といっても納期は過ぎてしまいましたが・・・他のハードが揃ってないことを言い訳にしてがんばってみます)

  • momoturbo
  • ベストアンサー率55% (49/88)
回答No.1

Timerイベントが走っている間は、自分に 返ってこないようにしてみてはどうでしょう? private sub Timer1_Timer() timer1.enabled=false '追加 do プリンターの処理 doevents loop timer1.enabled=true '追加 end sub

leftovers
質問者

お礼

早速試してみました。 問題の解決には至りませんでしたが、動作が安定しました。今回はありがとうございました。 よくよく調べてみるとやはりdoeventsは使い方に気をつけないとまずいらしいです。

leftovers
質問者

補足

ありがとうございます。テストしてみます。 一応不完全ながら現在のソースを以下に記します。 '標準モジュール内 'timeGetTime関数 Public Declare Function timeGetTime Lib "winmm.dll" () As Long 'グローバル変数 Dim BUF As String 'プリンタの状態を格納 '起動時 Private Sub Form_Load()     'ポートを開く    MSComm1.PortOpen = True 'プリンタの状態チェック用のタイマー開始 Timer1.Enabled = True Timer1.Interbal = 1000 End If End Sub '終了時 Private Sub Form_Unload(Cancel As Integer) 'プリンタの状態チェックタイマー終了 Timer1.Enabled = False 'ポートを閉じます。   Timer1.Interbal = 0 MSComm1.PortOpen = False End Sub 'プリンタからの状態データを取得する Private Sub MSComm1_OnComm() Dim TimeOut As Long Dim sTime As Long Dim eTime As Long Select Case MSComm1.CommEvent   '受信      Case comEvReceive 'タイマ開始 TimeOut = 1000 sTime = timeGetTime '全バッファ取得待ち Do 'タイムアウトなら If (TimeOut - eTime) < 0 Then 'ループを抜ける Exit Do End If eTime = (timeGetTime - sTime) Loop Until MSComm1.InBufferCount >= 82 'プリンタの状態取得       PBUF = MSComm1.Input End Select End Sub 'プリンタの状態チェックのタイマ Private Sub Timer1_Timer() Call CheckPrint End Sub 'プリンタの状態チェック Private Sub CheckPrint() Dim sTime As Long Dim eTime As Long Dim TimeOut As Long PBUF = "" 'プリンタの情報取得コマンド MSComm1.Output = "~HS" 'タイマ開始 TimeOut = 4000 sTime = timeGetTime eTime = 0 'コマンド取得待ち Do DoEvents 'コマンド取得なら If BUF <> "" Then 'ループを抜ける Exit Do End If eTime = (timeGetTime - sTime) 'タイムアウト Loop Until TimeOut - eTime < 0 If PBUF <> "" Then ・・・   ・・・   ・・・ End Sub