- PR -

タイマの実装について

1
投稿者投稿内容
のりてる
会議室デビュー日: 2006/06/10
投稿数: 9
投稿日時: 2008-03-18 19:16
5[msec]毎にある処理を実行したいと考えています。
まず、System.Threading.Timerの場合は、自環境の精度は約15msecしかでないためNGです。
そこで、Stopwatchクラスのカウンタ値に相当するもの(TotalMilliseconds)を使用し、
以下のコードを書いてみたところ、5msec毎に処理を実行させることができました。

ここで、質問なのですが
コード中のwhile文が重い処理になるため、これを緩和するためにThread.Sleep(1)を
while文内にいれようと考えておりますが、このようなやり方は一般的なのでしょうか?
それとも、何かOSのイベント待ちを使用する方法があるのでしょうか?



タイマ条件:5[msec]周期(許容範囲は5〜7[msec])
環境:VS2005(C#2.0)
OS:WinXP SP2
CPU:Core Duo(T2300)


コード:
  
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main( string[] args ) {

            Stopwatch sw = new Stopwatch();
            double period = 1; /// 2[msec]
            double p1 = sw.Elapsed.TotalMilliseconds - period; /// 前回値格納
            double p2 = sw.Elapsed.TotalMilliseconds; /// 今回値格納


            while(true) {
                if((p2 - p1) >= period) {
                    p1 = p2;

                    /// コールバック関数呼び出し
                    anyCallback();
                }
                p2 = sw.Elapsed.TotalMilliseconds;

            }
        }
        static void anyCallback() {/* ... */}
    }
}



以上、宜しくお願いします。
otf
ベテラン
会議室デビュー日: 2006/08/04
投稿数: 91
投稿日時: 2008-03-18 19:39
Thread.Sleep(0)

なら一般的だと思います。

http://msdn2.microsoft.com/ja-jp/library/d00bd51t(VS.80).aspx

http://www.microsoft.com/japan/msdn/net/general/win32map.aspx
SwitchToThreadの対応

あとAdvanced Windows 第4版 P235より
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-03-18 19:49
もし、Sleep を、「指定した秒数処理をしない」と理解されているなら、それは間違いです。これは、「最小でも指定した秒数は、処理を継続させない」です。
アプリケーションが、あることを完了するまでにかかる時間は、そのアプリケーションだけが関係しているわけではありません。他のすべてのプロセスが関係しています。今、Sleep にて、このスレッドの処理継続を放棄され、別のプロセスの処理を開始しました。そのプロセスで重い処理が走ると、再びこのスレッドに処理が戻ってきたとき、1msec 以上の時間が経過していたということは、普通にあります。

そういうことも考えた上で、言語の選定も含めて、設計されていますか?
のりてる
会議室デビュー日: 2006/06/10
投稿数: 9
投稿日時: 2008-03-18 20:32
otfさん、Jittaさん、さっそくのご返信ありがとうございます。


引用:

Thread.Sleep(0)
なら一般的だと思います。
http://msdn2.microsoft.com/ja-jp/library/d00bd51t(VS.80).aspx
http://www.microsoft.com/japan/msdn/net/general/win32map.aspx



なるほど、Sleep(0)で現在のスレッドの中断が実施されるわけですね。
そうするとCPUは、OSのスケジューリングにのっとって
ほかのプロセスやスレッドの処理をして、再び現在のスレッドに戻ってくるという
ことになるんですね。


引用:

もし、Sleep を、「指定した秒数処理をしない」と理解されているなら、それは間違いです。
これは、「最小でも指定した秒数は、処理を継続させない」です。



私の認識は、「指定した秒数CPUを開放する」でした。この考え方でもあっていますよね?
この考え方だと、
Sleep(0)は、CPUをいったん開放し、次のスケジューリングにてCPUを再取得する。
Sleep(1)は、CPUをいったん開放し、1[msec]以上経過後にCPUを再取得する。



引用:

そういうことも考えた上で、言語の選定も含めて、設計されていますか?


正直、なんとかなるだろうと思っておりまして、ここまで考えて設計しておりませんでした。(^^;
ただ、OS上で動作するアプリは自分が作成したプログラム(1プロセス数スレッド)
だけなので、不要なWIndowsのサービスを停止したり、現プログラム内のスレッド同士の調整などを
行うなどすれば、5〜7[msec]の周期タイマは実装できそうです。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-03-18 22:22
細かいところは覚えていませんが、.NET Framework では、3種類の Timer が使えます。そのうち、System.Windows.Forms.Timer は一番精度が悪く、これが 15msec とかいう単位だったような???

で、なんとなく、msec オーダーで制御が必要なら、その部分は C++ なりアセンブラなりにした方がいいのでは?と思いました。

追加
ご参考→ http://msdn2.microsoft.com/ja-jp/library/tb9yt5e6(VS.80).aspx
あと、下の方にあるリンクも

[ メッセージ編集済み 編集者: Jitta 編集日時 2008-03-18 22:27 ]
1

スキルアップ/キャリアアップ(JOB@IT)