皆様 久しぶりの質問です。
VC2005 C++ ネーティブコードでプログラムしています。
60ミリセカンド毎に約100回連続して処理をさせるプログラムをSetTimer(1,60,NULL);とOnTimer(UNIT nIDEvent);を使って書いています。
約6秒間の処理中にマウスを動かすとTimerイベントが中断したり、「半角/全角」からひらがなをタイプしても時々Timerイベント間隔に何故か変化があり困っています。マウスを動かさず、ひらがな入力もしなければ、正確にタイマーイベントが働いて正しく処理されています。
Sleep関数を使えば、処理が出来ますが、約6秒の間はマウス操作が出来ないし、キー入力も出来ないのでSleepは使えません。
解決策をお願いします。
なお、OnTimerの所には、if (nIDEvent == 1){を書いて余計なイベントは無視するようにしましたが、効果無しでした。
msでの精度求めるならマルチメディアタイマー使った方がいいですよ。
http://homepage2.nifty.com/DSS/VCPP/API/TimerPaformance.htm
メッセージのタイマーは精度が低いよ。
さらに
WM_TIMERは優先度が低いから
ほかのメッセージがあるとそれが先に実行されてから
WM_TIMERを処理することになるからね。
それと
1つのスレッドで同時に複数の処理は実行できませんから。
GUIとは別のスレッドで動かせば
GUIの処理に影響されにくくなるけど
別のスレッドで動いているということを念頭に入れないとね。
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関数は嫌ですね。何時もこれで悩んでいます。
よろしく
static関数からインスタンスを必要とする関数を呼ぶことはできません。
→つまりインスタンスが必要となる。
timeSetEvent関数の4番目の引数に注目してください。
ここに指定した値はtimeSetEvent関数の3番目の引数で指定した関数の
3番目の引数に渡されます。
類似スレです。
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200608/06080009.txt
インスタンスの意味も分からず、悪戦苦闘しています。
((CDigitalSoundCWView*)dwCookie)->OnTimerX();でも
旨く行きません。
答えをお教えいただけませんか? 宜しくお願いします。
>旨く行きません。
を第三者でもわかるように説明してくれますか?
14:10:02
> void CDSound:: SendTX()
18:41:38
> ((CDigitalSoundCWView*)dwCookie)->OnTimerX();
この2つのクラスの関係が分かりません。
1)timeSetEventはどこのクラスから呼んでいるのか
2)現在、timeSetEventの引数には何を入れているのか
を明記下さい。
とにかくデバッグはほぼ完了した模様なのですが、
あと少しのところで、エラー表示が出ます。
CDSOUND.exeのDx004303c4でバンドルされていない例外が発生しました。***との警告が出て止まっています。
止まった箇所は、
void CDSound:: SendTX()
{
TX ++;
// ここで処理をさせています。
}
のTX ++;の行で止まっています。 TXはheaderでpublic int TX;で設定しています。
CALLBACK Funcからタイマーイベント100回分が積算した時にSendTXに正常に飛んでいるようなのですが、呼び方が悪くてエラーが発生しているようです。
なお、Callback Funcには18:41に書き込んだのとは別に
((CDSound*)dwCookie)->OnTimerX();としています。
宜しくお願いします。
みいさんもおっしゃっていますが
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
皆様にご理解いただきたくて、実際のプログラムではなくて仮の名前を使ったりしたところ、間違えてしまいました。 大変失礼致しました。
お教えいただいたとおりに書いてみましたが、まだ、エラーで止まりましたので、少し長くなりますが、必要なプログラムの箇所抜粋して見ます。
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()への因数の渡し方がおかしいのでしょうか?
宜しくお願いいたします。
>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にどんな値が入っているのとか確認してみたりはしないのかなぁと。
Blueさん おかげ様で動き始めました。
TimeFuncでは無くてTimerFuncと違っていたので、デバッグするとエラーとなりましたが、デバッグも少しは慣れてきてすぐに間違いに気付き訂正しました。Hi.
お指図どおり2番目の引数が4ではなくて0に指定しましたが、CPU負担にそれほど影響はありませんか?
とにかくこれで、タイマーが動き始めたので、この後のプログラムに取り掛かります。
何を作っているかは、私のブログをお暇な時にご覧頂ければ幸いです。
http://blog.zaq.ne.jp/ja3clm/category/1/
ツイート | ![]() |