[リストへもどる]
一括表示

投稿時間:2004/05/19(Wed) 23:00
投稿者名:フレ
URL :
タイトル:
イベント処理中に違うイベントの処理を行う方法
はじめまして。
フレと申します。

イベント処理中に違うイベントの処理を
行うことができないかと悩んでおります。

VB6をはじめて4ヶ月程度なので
普通ではやらないような処理を
やろうとしているのかもしれませんが
ご容赦ください。

まず、タイマーイベントとボタンのクリックイベントに
以下のような処理を実装しました。
※標準EXEのフォームで実装しています。


Private Sub Timer1_Timer()

    Dim dateTime As Date
    
    dateTime = Now + (300 / 86400)
    Do While dateTime <= Now
        DoEvents
        Call Sleep(100)
    Loop

End Sub

Private Sub Command1_Click()

    Dim dateTime As Date
    
    dateTime = Now + (3600 / 86400)
    Do While dateTime <= Now
        DoEvents
        Call Sleep(100)
    Loop

End Sub


タイマーイベントの処理では5分間ループし続けるという
処理を実装しました。

ボタンクリックイベントの処理では1時間ループし続けるという
処理を実装しました。

アプリケーション起動後にタイマーイベントが
発生して5分間ループします。
5分間のループ中にボタンをクリックして
ボタンクリックイベントを発生させます。

タイマーイベントのループでは、
DoEvents を実行しているので
ボタンクリック直後にボタンクリックイベントの処理に
制御が移って処理が開始されます。

ここで、ボタンクリックイベントのループでも
DoEvents を実行しているので
タイマーイベントの処理にも制御が移ることがあるのかなぁと
想像していたのですが、
ずっとボタンクリックイベントのループから
制御が移りません。

1時間後にやっとボタンクリックイベントのループから抜けて、
イベントの処理が終了した瞬間に
タイマーイベントの処理に制御が移ります。
※とっくに5分以上過ぎているのでタイマーイベントの
 ループ処理はすぐに終了します。

希望としてはタイマーイベントは
5分間しかループしなくていいので
ボタンクリックイベントに制御が
移っていてループ処理が行われている最中でも
5分を経過したらタイマーイベントのループ処理は
終了して欲しいのですが、
ボタンクリックイベントの処理中に
一時的にタイマーイベントの処理に制御を
移すようなことはできないでしょうか?

ActiveX EXE を使って
スレッドモデルを「オブジェクトごとのスレッド」にすれば
ループの処理をそれぞれ別のスレッドで行うように実装できないかなぁ?とも
考えたのですが、標準EXEのフォーム等から
ActiveX EXE のクラスのメソッドを呼び出した場合、
5秒以内にメソッドが終了しないと
フォームをクリックした契機で
「コンポーネントが使用できません。」といった
ダイアログが表示されてしまいます。
※5秒という値は変更可能なようですが...

今回のような処理を行う場合は
みなさんはどのような実装を行われていますか?

今回の問題とは別問題ですけど、
5秒以内にメソッドの処理が終了しないといけない
ActiveX EXE は、あまり使い道がないような...(^^;)

長文で申し訳ございませんでした。

以上です。
よろしくお願いします。

投稿時間:2004/05/20(Thu) 09:48
投稿者名:徳田 新之助
Eメール:
URL :
タイトル:
Re: イベント処理中に違うイベントの処理を行う方法
> Private Sub Timer1_Timer()
>
>     Dim dateTime As Date
>    
>     dateTime = Now + (300 / 86400)
>     Do While dateTime <= Now
>         DoEvents
>         Call Sleep(100)
>     Loop
>
> End Sub
> タイマーイベントの処理では5分間ループし続けるという

タイマーイベントは約65秒が最長なので、永久にループすると思うのですが
Timer1.Interval と  Timer1.Enabled  等の設定はどこで
どのようにしておられますか?

投稿時間:2004/05/20(Thu) 13:34
投稿者名:フレ
Eメール:
URL :
タイトル:
Re^2: イベント処理中に違うイベントの処理を行う方法
こんにちはフレです。

徳田 新之助 さん、Say さんお返事ありがとうございます。
また、回答が遅くなってすみませんでした。

私の拙い文章だけだと質問の意味が
うまく伝わらないかな〜っと思って
既存のソースから簡単なサンプルを
提示したつもりだったのですが
Say さんからもご指摘のあったように
「dateTime <= Now」の条件が誤っていたりだとか
余計にわかりにくくしていたようです。

申し訳ございません。

「dateTime <= Now」ではなく「dateTime > Now」が正しいです。


> タイマーイベントは約65秒が最長なので、永久にループすると思うのですが
> Timer1.Interval と  Timer1.Enabled  等の設定はどこで
> どのようにしておられますか?
>
実際のアプリケーションの実装では
Timer1.Interval は、10000(10秒)を設定しております。
Timer1.Enabled は、デザイン時に False を設定しており、
アプリケーションの初期化処理が完了した時点で
True を設定するようにしております。

また、タイマーイベント内のループ処理も
最初にサンプル提示した300秒ではなく
実際のアプリケーションでは無限ループで実装しています。
(他のイベントの処理が終わるまでループし続ける同期処理のイメージ)

タイマーイベントは約65秒が最長とありますが、
もしかしてタイマーイベントの
イベントハンドラ関数(Timer1_Timer())の処理は
65秒以内に終了しないとまずかったりするのでしょうか?


やはり以下のようなシーケンスで処理をするのは
VBでは無理なんですかね〜。
※VBでは同期処理のようなことは
 普通しないものなのでしょうか?

以下の4項の処理をどうにか実現したいのですが...

1.タイマーイベント発生
    ↓
2.ボタンクリックイベント発生
    ↓
3.タイマーイベント処理内でDoEventsを実行した契機で
  ボタンクリックイベントに制御が移る
    ↓
4.ボタンクリックイベント処理内でタイマーイベントの処理に制御を戻したい。


以上です。
よろしくお願いします。

投稿時間:2004/05/20(Thu) 14:13
投稿者名:るしぇ
Eメール:
URL :
タイトル:
Re^3: イベント処理中に違うイベントの処理を行う方法
>65秒以内に終了しないとまずかったりするのでしょうか?
Interval の仕様をヘルプで確認してください。

難しい事しなければいいんでない?
[VB6.0]
Option Explicit

Private DateTimeX As Date

Private Sub Form_Load()
    With Me.Timer1
        .Interval = 10000 ' 10秒
        .Enabled = True
    End With
    With Me.Timer2
        .Interval = 1000 ' 1秒
        .Enabled = False
    End With
End Sub

Private Sub Command1_Click()

    DateTimeX = Now + (3600 / 86400)
    
    With Me.Timer2
        .Enabled = True
    End With
End Sub

Private Sub Timer1_Timer()
    With Me.Timer1
        .Enabled = False
    End With

    DateTimeX = Now + (300 / 86400)
    
    With Me.Timer2
        .Enabled = True
    End With
End Sub

Private Sub Timer2_Timer()
    
    DoEvents
    Call Sleep(100)

    If DateTimeX <= Now Then
    
        With Me.Timer2
            .Enabled = False
        End With
        
        MsgBox "時間ですよ。"
    End If
    
End Sub

投稿時間:2004/05/21(Fri) 16:08
投稿者名:フレ
URL :
タイトル:
Re^4: イベント処理中に違うイベントの処理を行う方法
こんにちはフレです。

るしぇさんご意見ありがとうございます。

> >65秒以内に終了しないとまずかったりするのでしょうか?
> Interval の仕様をヘルプで確認してください。
>
了解しました。

TimerコントロールのIntervalプロパティの値は
1 〜 65,535 の範囲内で設定可能であるということですよね!

「タイマーイベントは約65秒が最長なので、永久にループする」
といった旨のご指摘を誤って理解して
例えばIntervalに10秒を設定していて、
Timerイベントハンドラ関数の処理が
10秒を超えるようなことがある場合、
VBでは恐ろしいような事象が発生するのかな〜なんて
思ってしまいました。(・_・;)

TimerコントロールのIntervalって
定期的に指定された間隔で実行されることを
保証するものではなくて
最後にTimerイベントハンドラ関数の処理が終わってから
Interval値の時間だけ経過したら
次のTimerイベントが発生するものだと
思っております。

> 難しい事しなければいいんでない?
>
おっしゃるとおり!!(^^;)

VBのスキルがないのにがんばろうと
し過ぎているんだと思います。

違う方法での設計を検討しますが
もしも何か良い方法を見つけた場合は
後でこちらの掲示板にご報告します。

以上です。

投稿時間:2004/05/21(Fri) 18:04
投稿者名:るしぇ
Eメール:
URL :
タイトル:
Re^5: イベント処理中に違うイベントの処理を行う方法
> 「タイマーイベントは約65秒が最長なので、永久にループする」
> といった旨のご指摘を誤って理解して
> 例えばIntervalに10秒を設定していて、
> Timerイベントハンドラ関数の処理が
> 10秒を超えるようなことがある場合、
> VBでは恐ろしいような事象が発生するのかな〜なんて
> 思ってしまいました。(・_・;)
イベントはスタックされますので…そのうちスタック領域の不足で
落ちるんじゃないかと…。

今回の問題も最初の書き込みで
>1時間後にやっとボタンクリックイベントのループから抜けて、
>イベントの処理が終了した瞬間に
>タイマーイベントの処理に制御が移ります。
>※とっくに5分以上過ぎているのでタイマーイベントの
> ループ処理はすぐに終了します。
という結果になりましたが、これは1つの関数(この場合ボタンクリックイベントの関数)
の処理中は他のイベント(関数)の処理は後回しにされるから
いくら DoEvents しても意味が無い…ってことになってると思います。

一度ヘルプで↓この辺読んでみたらどうでしょう?
[Visual Studio 6.0 ドキュメント]
└[Visual Basic ドキュメント]
 └[Visual Basic の使用方法]
  └[プログラミング ガイド]
   └[Visual Basic を使ってできること]
    └[オブジェクト]
     └[クラスのイベントの追加]
       └[オブジェクトのイベントの処理]☆
  └[コンポーネント ツール ガイド]
   └[ActiveX コンポーネントの作成方法]
    └[コード コンポーネントの作成技術]
     └[非同期コールバックとイベント]
       └[イベントによる通知とコールバックによる通知]☆

そのものズバリを書いてるわけじゃないんですがなんとなく感じは
つかめるかと…

考えてみればイベントも1つの関数です。1つの関数の処理中に
他の関数の処理を許すと面倒なことになるでしょ?
ですから、イベントに限らず…ですが、処理中の関数を抜けることが
大事なんです。その辺りを意識して設計すればいいんじゃないでしょうか?

投稿時間:2004/05/24(Mon) 16:47
投稿者名:フレ
URL :
タイトル:
Re^6: イベント処理中に違うイベントの処理を行う方法
こんにちは、フレです。

るしぇさん回答ありがとうございます。

> > 「タイマーイベントは約65秒が最長なので、永久にループする」
> > といった旨のご指摘を誤って理解して
> > 例えばIntervalに10秒を設定していて、
> > Timerイベントハンドラ関数の処理が
> > 10秒を超えるようなことがある場合、
> > VBでは恐ろしいような事象が発生するのかな〜なんて
> > 思ってしまいました。(・_・;)
> イベントはスタックされますので…そのうちスタック領域の不足で
> 落ちるんじゃないかと…。
>
> 今回の問題も最初の書き込みで
> >1時間後にやっとボタンクリックイベントのループから抜けて、
> >イベントの処理が終了した瞬間に
> >タイマーイベントの処理に制御が移ります。
> >※とっくに5分以上過ぎているのでタイマーイベントの
> > ループ処理はすぐに終了します。
> という結果になりましたが、これは1つの関数(この場合ボタンクリックイベントの関数)
> の処理中は他のイベント(関数)の処理は後回しにされるから
> いくら DoEvents しても意味が無い…ってことになってると思います。
>
了解しました。
勘違いしたまま実装しちゃうと危険ですね。

> 一度ヘルプで↓この辺読んでみたらどうでしょう?
> [Visual Studio 6.0 ドキュメント]
> └[Visual Basic ドキュメント]
>  └[Visual Basic の使用方法]
>   └[プログラミング ガイド]
>    └[Visual Basic を使ってできること]
>     └[オブジェクト]
>      └[クラスのイベントの追加]
>        └[オブジェクトのイベントの処理]☆
>   └[コンポーネント ツール ガイド]
>    └[ActiveX コンポーネントの作成方法]
>     └[コード コンポーネントの作成技術]
>      └[非同期コールバックとイベント]
>        └[イベントによる通知とコールバックによる通知]☆
>
> そのものズバリを書いてるわけじゃないんですがなんとなく感じは
> つかめるかと…
>
> 考えてみればイベントも1つの関数です。1つの関数の処理中に
> 他の関数の処理を許すと面倒なことになるでしょ?
> ですから、イベントに限らず…ですが、処理中の関数を抜けることが
> 大事なんです。その辺りを意識して設計すればいいんじゃないでしょうか?
>
ヘルプの場所まで教えていただいて本当にありがとうございます。
とりあえず教えていただいたところあたりから参照しています。

結果、今回の私の希望を叶える実装として
ActiveX Exeを使って、ヘルプにあった非同期コールバック等の手法を使えば
いけるのではないかと考えています。

サンプル的なプログラムを作りながら検証していきます。
ありがとうございました。

投稿時間:2004/05/22(Sat) 22:02
投稿者名:よろずや
URL :
タイトル:
Re: イベント処理中に違うイベントの処理を行う方法
> ActiveX EXE を使って
> スレッドモデルを「オブジェクトごとのスレッド」にすれば
> ループの処理をそれぞれ別のスレッドで行うように実装できないかなぁ?とも
> 考えたのですが、標準EXEのフォーム等から
> ActiveX EXE のクラスのメソッドを呼び出した場合、
> 5秒以内にメソッドが終了しないと
> フォームをクリックした契機で
> 「コンポーネントが使用できません。」といった
> ダイアログが表示されてしまいます。

マルチスレッドとして動作するようにActiveX.Exeを作れば
ちゃんと動くはずですよ。
ActiveX内にタイマーを仕掛け、外から呼ばれたときはタイマーを起動して
すぐに呼び出し元に戻る。
直後に、ActiveX内でメソッドが動き始める。
メソッド終了前にメイン画面をクリックしても、問題ありません。

投稿時間:2004/05/24(Mon) 16:50
投稿者名:フレ
URL :
タイトル:
Re^2: イベント処理中に違うイベントの処理を行う方法
こんにちは、フレです。
よろずやさん回答ありがとうございます。

> > ActiveX EXE を使って
> > スレッドモデルを「オブジェクトごとのスレッド」にすれば
> > ループの処理をそれぞれ別のスレッドで行うように実装できないかなぁ?とも
> > 考えたのですが、標準EXEのフォーム等から
> > ActiveX EXE のクラスのメソッドを呼び出した場合、
> > 5秒以内にメソッドが終了しないと
> > フォームをクリックした契機で
> > 「コンポーネントが使用できません。」といった
> > ダイアログが表示されてしまいます。
>
> マルチスレッドとして動作するようにActiveX.Exeを作れば
> ちゃんと動くはずですよ。
> ActiveX内にタイマーを仕掛け、外から呼ばれたときはタイマーを起動して
> すぐに呼び出し元に戻る。
> 直後に、ActiveX内でメソッドが動き始める。
> メソッド終了前にメイン画面をクリックしても、問題ありません。
>
「ActiveX内にタイマーを仕掛け、外から呼ばれたときはタイマーを起動する」っていうのは
以前思いつきましたが、裏技っぽいのでちょっと敬遠していたのですが
るしぇさんからご指摘いただいてVBのヘルプを参照してみると
VBのヘルプにも普通に載っているんですね〜。

ActiveX Exeをぜんぜん使っていないので検証しつつ
教えていただいた方法で実装を検討したいと思います。

以上です。
教えていただいてありがとうございました。