お世話になっております.
今回はタイマーを使おうと思って,以下のソースを試しましたが,プログラムの目的を果たせませんでした.strボタンを押してタイマーを設定し50msecごとに同じ作業を繰り返し,stpボタンで終了させるのが目的です.
void CSampleDlg::OnButtonStr()
{
// TODO: Add your control notification handler code here
SetTimer(1, 50, NULL);//タイマーの設定 50msecごとに呼び出す
m_cStop.EnableWindow(TRUE);
m_cStart.EnableWindow(FALSE);
}
void CSampleDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your control notification handler code here
//----------
作業
//----------
CDialog::OnTimer(nIDEvent);
}
void CSampleDlg::OnButtonStp()
{
// TODO: Add your control notification handler code here
KillTimer(1); //タイマーのストップ
m_cStop.EnableWindow(FALSE); //stopボタン無効
m_cStart.EnableWindow(TRUE); //startボタン有効
}
デバッグしてもdead lockだといわれてしまいます.どこまでプログラムが動いているのかは確認できませんでしたが,どこかタイマーの使い方がおかしいのでしょうか?宜しくお願いします.
まず前提条件として Windows の WM_TIMER というのは優先順位が低く、
計測機器から測定データを定期的に取得する必然があるなどの理由で
「必ず 50msec ごとに確実に処理がなされなければならない」
という仕様を実現するためであれば、そもそも原理的に使えない代物だ
ってあたりの理解はOK?
50msec を指定しても 1000msec 以上遅れるなんてことはざら。
提示のコード断片だけだと悪いところはみつからない。
「作業」の処理に 50msec 以上かかっていたりする可能性とかは検討済み?
どこでデットロックするの?それ書かないと。
あ、失礼。確認できないのか。
間隔長くして(1時間とか)OnTimer()の中をトレースしてみては?
MFCはあまり使っていないので、間違えているかもしれませんが、
CSampleDlg::OnTimer()の中で処理が完結しているのでしたら、
CDialog::OnTimer(nIDEvent)は不要なのではないでしょうか。
tetrapodさん,そださん,Hazard52さんご返信ありがとうございます.
WM_TIMERがそんなにあやふやなものだとは,知りませんでした...
時間を守らせるには他の方法でやる必要がありそうです.
「作業」の処理に対して十分な時間をあけて,タイマーを設定しているので,作業が終わる前にタイマーがきてしまうことはないと思います.
TRACEで確かめたところ,OnTimerが実行されていないようではあります.
CDialog::OnTimer(nIDEvent)に関してですが,消してみたりしましたが,うまく行きませんでした.
あと理由は分かりませんが,dead lockはデバッグに表示されなくなりました.
>TRACEで確かめたところ,OnTimerが実行されていないようではあります.
ブレークポイントの設置個所はOnTimer内だけですか?
SetTimerを実行しているところもトレースしていると最初の1回を見逃すかもしれません。
それでもタイマーが起動していないというならば、SetTimerの戻り値を調べ正常に実行されているか確かめるべきです。
>あと理由は分かりませんが,dead lockはデバッグに表示されなくなりました.
タイマの間隔を長くした後でしょうか。同時に2つ以上のスレッドが動いていないならばデッドロックはその定義上起こりえません。
作業部分を抜いたソースで試すか
新しいプロジェクトをつくって、タイマーだけの実験をしてみてはどうでしょうか?
そださん,rinさんご返信ありがとうございます.
作業部分を抜かしたり,あちこちtraceを入れてみましたが,やはりOnTimerが実行されていないようだったので,どこで何か宣言し損ねてるのかと思い,色々調べてメッセージマップのところにWM_TIMER()を追加したらプログラムが動きました.参考にしていた本に記載がなかったので,何も入れていませんでした...
BEGIN_MESSAGE_MAP(CSampleDlg, CDialog)
//{{AFX_MSG_MAP(CTakeuchiDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_STR, OnButtonStr)
ON_BN_CLICKED(IDC_BUTTON_STP, OnButtonStp)
ON_WM_TIMER() //追加
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
初歩的な間違いで申し訳ありませんでした.
相談に乗っていただきありがとうございました.
デッドロックに関してですが,どうしてデバッグに表示されたのか分からないうちに表示されなくなっていました.これもなぞではありますが.
解決したようですが、一応。
メッセージを追加してなかったようですが、ひょっとして全部手入力でやっているのですか?
VCを使っているかは不明ですが、
VCに任せて(ClassWizard or イベントハンドラの追加)みては?
やり方はヘルプや参考書を見てください。
ツイート | ![]() |