Windows サービス プロジェクトで使用する前に、小さなテスト プロジェクトを実行していますSystem.Threading.Timer
。 問題なく動作していますが、1 ~ 2 分後にタイマーが自動的に停止します。
テスト プロジェクトの完全なソースは次のとおりです。
using System;
using System.Windows.Forms;
using System.Threading;
namespace studyTimers {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
TimerCallback timerDelegate = new TimerCallback(tick);
System.Threading.Timer testTimer = new System.Threading.Timer(timerDelegate, null, 1000, 1000);
}
void tick(Object obj) {
if (label1.InvokeRequired) {
label1.Invoke(new MethodInvoker(() => tick(obj)));
} else {
label1.Text = DateTime.Now.ToString();
}
}
}
}
目標は明らかに、ラベルを現在の時刻で更新することです。しばらくすると更新が停止することに気づきました。これはなぜでしょうか?
ベストアンサー1
Windows フォームでタイマーが必要な場合は、フォームに をドロップします。55ミリ秒よりも高い解像度が必要でない限り、System.Windows.Forms.Timer
を使用する理由はありません。System.Threading.Timer
タイマーが「停止」する理由は、ガベージ コレクションされているためです。Form1_Load
タイマーをローカル変数としてのみ宣言しているため、メソッド内でタイマーがスコープ外になることがあります。タイマーを「有効」に保つには、GC がタイマーがまだ必要であることを認識できるように、タイマーをフォーム クラスのプライベート フィールドに設定する必要があります。
言い換えると:
public partial class Form1 : Form
{
private System.Threading.Timer testTimer;
...
public void Form1_Load(object sender, EventArgs e)
{
TimerCallback timerDelegate = new TimerCallback(tick);
testTimer = new System.Threading.Timer(timerDelegate, null, 1000, 1000);
}
}
しかし、この場合も、System.Windows.Forms.Timer
ツールボックス内の実際のコンポーネントである を使用する方が簡単です。これをフォームにドロップするだけで済みます。
編集- コメントからわかるように、これが単なるテストアプリで、実際のアプリケーションがWindowsサービスにある場合、できないそのために使用します。範囲外にならSystem.Windows.Forms.Timer
ないように注意してください。System.Threading.Timer