いつもお世話になっております。
現在3つのタイマーがあります。(3つ目は起動していません)
1のタイマーは、データを取得しています。取得方法として終わり文字が来るまでDO文にてぐるぐるまわしています。その中でDOEVENTSを入れています。
2のタイマーは、データを解析しています。(解析は10分感覚です)
×ボタンにてフォームが閉じられた時、解析時間が来ていれば解析処理をして終了、もし解析時間が来ていなければ即終了としたいのですがなかなかうまくいきません。
タイマーが起動直後の時は上手くアンロード処理が働くのですが、タイマーが起動し、しばらくした時にフォームを閉じようとすると処理すらしてくれずDOEVENTSを外すと「応答なし」になってしまいます。
Private Sub MDIForm_QueryUnload(Cancel As Integer, UnloadMode As Integer)
Dim L%, C As Object
On Error Resume Next
'メイン以外のフォームを確実にアンロード
If Not RunMODE.MAINTE Then
'メンテナンスモード以外はユーザが閉じる操作をキャンセル
If UnloadMode = vbFormControlMenu Then
Cancel = True
Exit Sub
End If
End If
For Each C In Forms
If C.Name <> "MDIMain" Then
If C.Name = "frmMain" Then
frmMain_Unload = False
Unload C
Do
If frmMain_Unload Then
Exit Do
End If
Loop
Else
Unload C
End If
End If
Next
End Sub
Private Sub MDIForm_Unload(Cancel As Integer)
Set MDIMain = Nothing
End Sub
Private Sub Timer1_Timer()
Dim kei As Single
Dim sui As Single
Dim Ret As Integer
Static Flag As Boolean
If Unload_Flag Then
'プログラムを終了中かどうか
With Timer1
.Enabled = False
.Interval = 0
End With
If Timer2.Enabled = False And Timer3.Enabled = False Then
Unload Me
End If
call データ取得処理
Exit Sub
End If
end sub
Private Sub Timer2Timer()
Dim kei As Single
Dim sui As Single
Dim Ret As Integer
Static Flag As Boolean
If Unload_Flag Then
'プログラムを終了中かどうか
With Timer2
.Enabled = False
.Interval = 0
End With
If Timer1.Enabled = False And Timer3.Enabled = False Then
Unload Me
End If
call データ取得処理
Exit Sub
End If
end sub
private sub データ取得処理
do
処理
DOEVENTS
loop
end sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
Dim FUN As Boolean
If Timer1.Enabled Or Timer2.Enabled Or Timer3.Enabled Then
'どれかのタイマーが起動していれば
Unload_Flag = True
'Form_Unloadイベントを発生させないために
Cancel = 1
Exit Sub
End If
With frmShuttle
If .Port1.Opened Then
FUN = .Port1.Close
End If
End With
Cancel = 0
frmMain_Unload = True
End Sub
Private Sub Form_Unload(Cancel As Integer)
Debug.Print "frmMAIN_Ture"
Set frmMain = Nothing
End Sub
長々となりすみませんが 宜しくお願い致します
まずはコンパイルの通るサンプルを出してください
あと、関係ないかもしれませんが、フォームを閉じようとしたとき
データ取得処理やら、データ解析処理が走っていて、その中でなにか
フォーム上のコントロールにアクセスしていれば、そのフォームは再度
ロードされてしまいますよ。
Xボタンで終了させるのをやめて、終了用のコマンドボタンを用意すれば話は簡単そうですが・・・
返信ありがとうございます。
終了ボタンを用意するというのは仕様上できないのでやめておきます。
Public ENDFLAG AS Boolean
pUBLIC KeisokuF AS Boolean
Private Sub Form_Load()
Timer1.Interval = 3000
Timer2.Interval = 1000
Timer3.Interval = 500
Timer1.Enabled = True
Timer2.Enabled = True
Timer3.Enabled = False
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
ENDFLAG = True
Do
If KeisokuF = False Then
Timer1.Enabled = False
Exit Do
End If
DoEvents
Loop
Unload Me
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set Form1 = Nothing
End Sub
Private Sub Timer1_Timer()
Static flag As Boolean
If flag Then Exit Sub
flag = True
Call keisoku
flag = False
End Sub
Private Sub keisoku()
Dim tim As Integer
Dim t1 As Date
Dim t2 As Date
Dim str As String
If ENDFLAG Then
Exit Sub
End If
t1 = Now
KeisokuF = True
Do
str = "i"
str = str & str
tim = DateDiff("s", t1, Now)
If tim > 10 or ENDFLAG = True Then
Exit Do
End If
DoEvents
Loop
KeisokuF = False
End Sub
以上がソースです
Timerからkeisokuを呼び出しその中で10秒間待っているだけなのですが
keisoku処理の途中で×ボタンでフォームが閉じられた場合そのDO文の中でPGが停止されてしまうのですがどのように対処すればいいのでしょうか?
タイマー2でもデータを取得に行ってるんですね。
タイマー1の call データ取得処理 は確実に終了しているのですか?
>DOEVENTSを外すと「応答なし」になってしまいます
を見る限り、データ取得処理が終わってないんでしょう
private sub データ取得処理のループ内のDoEventの後ろにでも
If Unload_Flag Then EXIT DO
を入れて試してみては?
なんだかソースを見る限り基礎的なことをいまいち理解してないようなので
簡単なサンプルを書いておきます。
あなたの提示したソースは、ここをこうすればというレベルのソースになって
いませんので。
以下はフォームにタイマー1個貼り付けて、タイマー内の処理が実行された
場合、タイマー内の処理が終了するまでプログラムを終了しないという
サンプルです。
Private Sub Form_Load()
Timer1.Interval = 10000
Timer1.Enabled = True
End Sub
Private Sub Timer1_Timer()
Dim t As Date
Static bsy As Boolean
If bsy Then Exit Sub
bsy = True
t = Now
Do While DateDiff("s", t, Now) < 10
Debug.Print Now
DoEvents
Loop
bsy = False
End Sub
Do Loopに頼りすぎです。
Public flgRequestEnd As Boolean
Public flgKaiseki As Boolean
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
If flgKaiseki Then
flgRequestEnd = True
Me.Caption = "終了予約中"
Cancel = 1
End If
End Sub
Private Sub keisoku()
Dim timeStart As Date
timeStart = Now
flgKaiseki = True
Me.Caption = "計測中"
Do
If DateDiff("s", timeStart, Now) > 10 Then
Exit Do
End If
DoEvents
Loop
Me.Caption = "計測準備中"
flgKaiseki = False
If flgRequestEnd Then
Unload Me
End If
End Sub
Private Sub Form_Load()と
Private Sub Timer1_Timer()は
そのままで良いので省略してます。
ちょっとこれでやってみてください。
すみません いろいろと試していて返信できませんでした。(_ _
最終的に
終了ボタンを押された時、終了チェックタイマーを動かしその中で
全ての処理が終わるまで永遠とタイマーを動かし、終了処理をすると
うまくいきましたのでそれを採用しました。
以下は変更前のPGの話です。
計測タイマーが起動すると、3秒周期でデータを採取しにいきます。
データ採取中はDO〜LOOPでまわし中にDOEVENTS
をかましていました。
そしてそのDO〜LOOP中に、閉じるボタンを押されるとクエリーアンロードイベントが発生し、その中で終了フラグが立つまで、その中でもDO〜LOOPでまわしています。そのLOOP内でもDOEVENTSはかましています。(この時計測タイマーは動いています)
しかし、流れは計測タイマー終了後→クエリーアンロードとなってほしいのですが、DOEVENTSによりクエリーアンロードイベントのDO〜LOOP内を永遠と繰り返すだけでした。
以前のソースです
Option Explicit
Private ENDFLAG As Boolean
Private SampFlag As Boolean
Private KEISOKU_TIME As Date
Private Sub Form_Load()
KEISOKU_TIME = Format(DateAdd("d", 1, Now), "yyyy/mm/dd 00:00:00")
Timer1.Interval = 3000
Timer1.Enabled = True
Timer2.Enabled = True
Timer2.Interval = 300
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
ENDFLAG = True
Do
If SampFlag = False Then
Exit Do
End If
DoEvents
Loop
Debug.Print "おしまい"
End Sub
Private Sub Timer1_Timer()
Static flag As Boolean
If ENDFLAG Then
Timer1.Enabled = False
Timer1.Interval = 0
If Timer2.Enabled = False Then
Unload Me
End If
Exit Sub
End If
If flag Then Exit Sub
flag = True
SampFlag = True
Call keisoku
SampFlag = False
flag = False
End Sub
Private Sub Timer2_Timer()
Static flag As Boolean
If ENDFLAG Then
Timer2.Enabled = False
Timer2.Interval = 0
If Timer1.Enabled = False Then
Unload Me
End If
Exit Sub
End If
If flag Then Exit Sub
flag = True
If KEISOKU_TIME <= Now Then
'日替わり処理
End If
flag = False
End Sub
Private Sub keisoku()
Dim t1 As Date
Dim i As Integer
t1 = Now
i = 0
Do
i = i + 1
Debug.Print i
If DateDiff("s", t1, Now) > 20 Then
Debug.Print "タイムアウト"
End If
DoEvents
Loop
End Sub
このソース実行すると、タイマーが起動していない、またはタイマー起動直後であれば終了処理が働きますが、CALL KEISOKU中に終了ボタンを押すと固まります。
この謎が知りたかったのですが、ようやく分かりました。
長文になりすみません。
数日間ご指摘ありがとうございました。(^^
我龍院さん 本当にありがとうございます。
今までDO〜LOOPばかり使用していたので、違った手法を教えていただきありがとうございました。
これからいろいろお世話になると思いますが宜しくお願い致します。
ツイート | ![]() |