SetTimer OnTimerのイベント間隔を変わらないようにするには

解決


紅輝  2007-10-16 07:16:52  No: 66578

皆様  久しぶりの質問です。
VC2005  C++  ネーティブコードでプログラムしています。
60ミリセカンド毎に約100回連続して処理をさせるプログラムをSetTimer(1,60,NULL);とOnTimer(UNIT nIDEvent);を使って書いています。
約6秒間の処理中にマウスを動かすとTimerイベントが中断したり、「半角/全角」からひらがなをタイプしても時々Timerイベント間隔に何故か変化があり困っています。マウスを動かさず、ひらがな入力もしなければ、正確にタイマーイベントが働いて正しく処理されています。
Sleep関数を使えば、処理が出来ますが、約6秒の間はマウス操作が出来ないし、キー入力も出来ないのでSleepは使えません。
解決策をお願いします。
なお、OnTimerの所には、if (nIDEvent == 1){を書いて余計なイベントは無視するようにしましたが、効果無しでした。


みい  2007-10-16 08:47:41  No: 66579

msでの精度求めるならマルチメディアタイマー使った方がいいですよ。
http://homepage2.nifty.com/DSS/VCPP/API/TimerPaformance.htm


wclrp ( 'o')  2007-10-16 09:24:06  No: 66580

メッセージのタイマーは精度が低いよ。

さらに
WM_TIMERは優先度が低いから
ほかのメッセージがあるとそれが先に実行されてから
WM_TIMERを処理することになるからね。

それと
1つのスレッドで同時に複数の処理は実行できませんから。

GUIとは別のスレッドで動かせば
GUIの処理に影響されにくくなるけど
別のスレッドで動いているということを念頭に入れないとね。


紅輝  2007-10-16 23:10:02  No: 66581

timeSetEventの方法ご教授有難うございます。

dwTimerID = timeSetEvent(5,4,timeFunc, 0, TIME_PERIODIC);
でタイマー起動させ、
void CALLBACK timeFunc(UINT uiID, UINT uiNo, DWORD dwCookie, DWORD dwNo1, DWORD dwNo2){
  static int = 0;
  i++;
  if (i == 100) {  
      SendTX();
      i = 0;  
  }
}
void CDSound:: SendTX()
{
  // ここで処理をさせる

上記のようなプログラムをデバッグするとCALLBACK関数内のSendTX()の行でエラーとなって前に進みません。  CDSound::SendTX();等と書いてもだめです。
CALLBACK関数から普通の関数を呼び出すにはどうすれば好いですか?
Callback関数は嫌ですね。何時もこれで悩んでいます。
よろしく


Blue  2007-10-16 23:59:47  No: 66582

static関数からインスタンスを必要とする関数を呼ぶことはできません。
→つまりインスタンスが必要となる。

timeSetEvent関数の4番目の引数に注目してください。
ここに指定した値はtimeSetEvent関数の3番目の引数で指定した関数の
3番目の引数に渡されます。

類似スレです。
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200608/06080009.txt


紅輝  2007-10-17 03:41:38  No: 66583

インスタンスの意味も分からず、悪戦苦闘しています。
((CDigitalSoundCWView*)dwCookie)->OnTimerX();でも
旨く行きません。
答えをお教えいただけませんか?  宜しくお願いします。


Blue  2007-10-17 05:23:39  No: 66584

>旨く行きません。
を第三者でもわかるように説明してくれますか?


みい  2007-10-17 06:04:32  No: 66585

14:10:02
> void CDSound:: SendTX()
18:41:38
> ((CDigitalSoundCWView*)dwCookie)->OnTimerX();
この2つのクラスの関係が分かりません。

1)timeSetEventはどこのクラスから呼んでいるのか
2)現在、timeSetEventの引数には何を入れているのか
を明記下さい。


紅輝  2007-10-17 06:11:29  No: 66586

とにかくデバッグはほぼ完了した模様なのですが、
あと少しのところで、エラー表示が出ます。
CDSOUND.exeのDx004303c4でバンドルされていない例外が発生しました。***との警告が出て止まっています。
止まった箇所は、
void CDSound:: SendTX()
{
    TX ++;  
// ここで処理をさせています。

のTX ++;の行で止まっています。  TXはheaderでpublic int TX;で設定しています。
CALLBACK Funcからタイマーイベント100回分が積算した時にSendTXに正常に飛んでいるようなのですが、呼び方が悪くてエラーが発生しているようです。
なお、Callback Funcには18:41に書き込んだのとは別に
((CDSound*)dwCookie)->OnTimerX();としています。
宜しくお願いします。


Blue  2007-10-17 09:29:28  No: 66587

みいさんもおっしゃっていますが
SendTXとOnTimerXの関係が見えないのですが。
(まったく第三者に伝わっていないような)

>dwTimerID = timeSetEvent(5,4,timeFunc, 0, TIME_PERIODIC);

dwTimerID = timeSetEvent(5, 0,timeFunc, reinterpret_cast<DWORD_PTR>(this), TIME_PERIODIC);
// 第2引数に4を指定しているのは?

>void CALLBACK timeFunc(UINT uiID, UINT uiNo, DWORD dwCookie, DWORD dwNo1, DWORD dwNo2){

void CALLBACK timeFunc(UINT uiID, UINT uiNo, DWORD_PTR dwCookei, DWORD_PTR dwNo1, DWORD_PTR dwNo2);

>  static int = 0;
>  i++;
>  if (i == 100) {  
>      SendTX();

    reinterpret_cast<CDSound*>(dwCookei)->SendTX();
>      i = 0;  
>  }
>}

MSDN timeSetEvent
http://msdn2.microsoft.com/en-us/library/ms713423.aspx


紅輝  2007-10-17 19:30:37  No: 66588

皆様にご理解いただきたくて、実際のプログラムではなくて仮の名前を使ったりしたところ、間違えてしまいました。  大変失礼致しました。
お教えいただいたとおりに書いてみましたが、まだ、エラーで止まりましたので、少し長くなりますが、必要なプログラムの箇所抜粋して見ます。
DigitalSoundCWView.cpp ファイル
コールバック関数の宣言
void CALLBACK timerFunc(UINT uiID, UINT uiNo, DWORD dwCookie, DWORD dwNo1, DWORD dwNo2);
***************
void CDigitalSoundCWView::OnInitialUpdate()
{  このイニシアルファイルの中で
    dwTimerID = timeSetEvent(5, 4, timerFunc, 0, TIME_PERIODIC);
    を起動

注:  5ミリセカンド毎のイベントを発生。  2番目の4は0にするとCPU負担が大きくなるとのことなので
別のサンプルプログラムを参照して4としています。
***************
void CALLBACK timerFunc(UINT uiID, UINT uiNo, DWORD dwCookie, DWORD dwNo1, DWORD dwNo2)
{        //  10ミリセカンド毎にOnTimerX()関数を呼び出す。
  static int TimeCount = 0;
  TimeCount++;
  if (TimeCount >= 2){
    reinterpret_cast<CDigitalSoundCWView*>(dwCookie)->OnTimerX();
    TimeCount = 0;
  }
}  
***************
void CDigitalSoundCWView::OnTimerX()
{
  int i;
  int len;
  
  CString ss;
  CString TxCWss;

  TXDotCount ++;    ⇔  ここでエラーとなって止まってしまいます。
  if (TXDotCount >= Tx[TXSpeed]){
    //この関数の中で色々と処理をさせています    
    TXDotCount = 0;
        }
}
**************
// DigitalSoundCWView.h  ファイル
#pragma comment(lib, "winmm.lib")// timeSetEventを使用するのに必要

DWORD    dwTimerID;    // SetTimerEvent開設用
void    OnTimerX();    // Timer処理
int    TXDotCount;    // 短点数

エラーとなって止まった時の表示は
DigitalSoundCW.exe の 0x004303c4 でハンドルされていない例外が発生しました: 0xC0000005: 場所 0x00002018 を読み込み中にアクセス違反が発生しました。
です。
宜しくお願いいたします。
なお、TXDotCount ++;の行の書き方、または.hファイルの記載がおかしいのでしょうか?  あるいは、ONTimerX()への因数の渡し方がおかしいのでしょうか?
宜しくお願いいたします。


Blue  2007-10-17 19:35:32  No: 66589

>dwTimerID = timeSetEvent(5, 4, timerFunc, 0, TIME_PERIODIC);
thisを指定するといっているのだけど。

>timeSetEvent関数の4番目の引数に注目してください。
>ここに指定した値はtimeSetEvent関数の3番目の引数で指定した関数の
>3番目の引数に渡されます。

>>dwTimerID = timeSetEvent(5,4,timeFunc, 0, TIME_PERIODIC);
>↓
>dwTimerID = timeSetEvent(5, 0,timeFunc, reinterpret_cast<DWORD_PTR>(this), TIME_PERIODIC);

というか、デバッグしてdwCookieにどんな値が入っているのとか確認してみたりはしないのかなぁと。


紅輝  2007-10-17 20:16:19  No: 66590

Blueさん  おかげ様で動き始めました。
TimeFuncでは無くてTimerFuncと違っていたので、デバッグするとエラーとなりましたが、デバッグも少しは慣れてきてすぐに間違いに気付き訂正しました。Hi.
お指図どおり2番目の引数が4ではなくて0に指定しましたが、CPU負担にそれほど影響はありませんか?
とにかくこれで、タイマーが動き始めたので、この後のプログラムに取り掛かります。
何を作っているかは、私のブログをお暇な時にご覧頂ければ幸いです。
http://blog.zaq.ne.jp/ja3clm/category/1/


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

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






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