C#と.NET4.0を使用して新しいWindowsフォームアプリケーションを作成しました。60分の1秒ごとに自動的に呼び出す必要のある関数があります。私の問題は、この関数をどこで呼び出すかわからないことです。.NETフォームには、組み込みの更新時イベントがないようです。
この関数を60分の1秒ごとに呼び出すにはどうすればよいですか?初心者の質問ならごめんなさい。
16ミリ秒(1/60秒)ごとにコールバックを呼び出すようにタイマーを設定できます。
@spenderが述べた重要なポイント:これについて非常に正確なタイミングが必要な場合、たとえば正確に1/60秒ごとの精度が必要な場合、このソリューションには満足できません。Windowsは、その流れの中で高解像度のタイミングをネイティブにうまく実行しません。言及のための@spenderへの小道具。
これは、プレーンなバニラクラスでどのように見えるかを大まかに示したサンプルクラスであるため、フォームに適合させる必要があります。
これをバックグラウンドスレッドで呼び出すこともできますが、WinFormsを初めて使用する場合は、小さなチャンクから始めます。最初にタイマーを試してから、そこから行きましょう。
class Demo{
System.Timers.Timer myTimer;
void InitializeTimer(){
myTimer = new Timer(16); // elaps every 1/60 sec , appx 16 ms.
myTimer.ElapsedEventHandler+=new ElapsedEventHandler(myTimerEventHandler); //define a handler
myTimer.Enabled=true; //enable the timer.
}
void myTimerEventHandler(object sender, ElapsedEventArgs e){
// do your thing here
}
}
編集:バックグラウンドスレッドの作成と呼び出されたベースのGUI更新のための追加のデモコード
以下の私のコメントで述べたように、これは私が望むほど洗練されていませんが、それは重要なポイントを示していると思います。スレッド呼び出しをバックグラウンドに移動するためのBackgroundWorkerスレッドを定義します。スレッドコールバックは、Invokeを呼び出す必要があるかどうかをチェックし、デリゲート呼び出しを介してそれ自体に直接コールバックし、「if(InvokeRequired)」ステートメントの「else」ブロックでカスタムフォームを更新できるようにします。一言で言えば、バックグラウンドスレッドが開始し、タイマーを開始します。タイマーが経過すると、バックグラウンドスレッドでアップデーターを呼び出します。アップデーターは、Invokeを呼び出す必要があるかどうかを確認し、呼び出す必要がある場合は、メソッドへのリコールを通じてGUIスレッドにスレッドコンテキストスイッチを実行します。 GUIの更新。カスタム更新コードをその「else」ブロックに配置します。これがお役に立てば幸いです!!!
public partial class Form1 : Form
{
delegate void FormUpdateDelegate(object sender, ElapsedEventArgs e);
public BackgroundWorker backgroundThread;
System.Timers.Timer foo;
Random colorgen = new Random();
public Form1()
{
InitializeComponent();
backgroundThread = new BackgroundWorker();
backgroundThread.DoWork+=new DoWorkEventHandler(backgroundThread_DoWork);
backgroundThread.RunWorkerAsync();
}
public void formUpdater(object sender, ElapsedEventArgs e)
{
if (InvokeRequired)
{
FormUpdateDelegate d = new FormUpdateDelegate(formUpdater);
Invoke(d, new object[] { sender, e });
}
else
{
// Do your form update here
this.label1.ForeColor = Color.FromArgb(colorgen.Next());
}
}
public void backgroundThread_DoWork(object sender, DoWorkEventArgs e)
{
foo = new System.Timers.Timer(16);
foo.Elapsed += new ElapsedEventHandler(formUpdater);
foo.Start();
}
}
これをコンソールアプリケーションで設定するだけで、毎秒正常に実行されます。
var timer = new System.Timers.Timer(1000);
timer.Enabled = true;
timer.Elapsed += new ElapsedEventHandler(delegate(object sender, ElapsedEventArgs eventArgs)
{
Console.WriteLine("Elapsed");
});
少なくとも20
1秒あたりの精度が必要な場合は、システムタイマーを期待するのは悪い習慣です。
次のようなサイクルを使用することをお勧めします
Timespan timePerFrame = Timespan.FromMilliseconds(16);
while (_isRunning)
{
Stopwatch timer = Stopwatch.StartNew()
// Action.
while (timer.ElapsedMilliseconds < timePerFrame) { /* Nothing? */ }
}
システムが高精度のストップウォッチをサポートしている場合、これにより完全な精度が得られます。(.IsHighResolution
フィールド)。