System.Timers.TimerとSystem.Threading.Timerの比較


565

私は最近の可能なタイマーのいくつかをチェックアウトし、されているSystem.Threading.TimerSystem.Timers.Timer(彼らは、スレッドプールをサポートするので)私に入用に見えるものです。

私はゲームを作っており、すべてのタイプのイベントを、異なる間隔などで使用する予定です。

どれが一番いいですか?

回答:


363

この記事はかなり包括的な説明を提供します:

.NET Frameworkクラスライブラリのタイマークラスの比較-.chmファイルとしても利用可能

具体的な違いSystem.Timers.Timerは、マルチスレッドアプリケーションを対象としているためSynchronizationObject、そのプロパティを介してスレッドセーフであるのに対して、System.Threading.Timer皮肉なことに、最初からスレッドセーフではないようです。

あなたの間隔がどれほど小さいかということに関係しているので、私は2つの間に違いがあるとは信じていません。


69
「System.Windows.Forms.Timerとは異なり、System.Timers.Timerクラスはデフォルトで、共通言語ランタイム(CLR)スレッドプールから取得したワーカースレッドでタイマーイベントハンドラーを呼び出します。 。[...] System.Timers.Timerクラスは、このジレンマに対処する簡単な方法を提供します。これは、パブリックSynchronizingObjectプロパティを公開します。このプロパティをWindowsフォーム(またはWindowsフォーム上のコントロール)のインスタンスに設定すると、 Elapsedイベントハンドラーのコードが、SynchronizingObjectがインスタンス化されたのと同じスレッドで実行されることを確認してください。
mico

7
Threading.TimerMSDN記事のスレッドセーフセクションによると、完全にスレッドセーフです...
Pieter

62
System.Threading.Timer「皮肉なことに」スレッドセーフではなくSystem.Threading.Thread、プールを通じて取得されたスレッドも同様です。これらのクラスがあなたの手を握らず、lockキーワード自体の使用を管理しているからといって、これらのクラスがスレッドセーフではないという意味ではありません。あなたにも言うかもしれないSystem.Threading.Thread、それはまさに真のようなので、スレッドセーフではありません。
Kirk Woll 2013年

8
また、System.Timer.Timerの間隔はInt32にのみ設定できますSystem.Threading.Timerの間隔は最大Int64にできます
ブレント

11
この非常に誤解を招く(せいぜい)回答が受け入れられ、非常に高く投票されているのは残念です。答え自体の唯一の重要な声明は単に間違っています。SynchronizingObjectタイマーオブジェクト自体はスレッドセーフではありません。タイマーイベントを処理するコードが特定のスレッドで呼び出されることを確認するだけです(そのプロパティを適切に設定した場合)。ドキュメントに明記されているように、タイマーオブジェクト自体はスレッドセーフであるとは限りません。一方、System.Threading.Timerオブジェクトスレッドセーフである明確に文書化されています。
Peter Duniho

169

System.Threading.Timer単純なタイマーです。スレッドプールスレッドで(ワーカープールから)コールバックします。

System.Timers.TimerあるSystem.ComponentModel.ComponentラップことSystem.Threading.Timer、及び特定のスレッドにディスパッチするために使用されるいくつかの追加機能を提供します。

System.Windows.Forms.Timer代わりに、ネイティブメッセージのみのHWNDをラップし、ウィンドウタイマーを使用します。をして、そのHWNDメッセージループでイベントを発生させます。

アプリにUIがなく、可能な限り最も軽量で汎用的な.Netタイマーが必要な場合(独自のスレッド化/ディスパッチを理解して満足しているため) System.Threading.Timer、フレームワークと同じくらい優れています。

想定される「スレッドセーフではない」問題が何であるかについては、完全には明確ではありませんSystem.Threading.Timer。おそらくそれはこの質問で尋ねられたものと同じです:System.Timers.TimerとSystem.Threading.Timerのスレッドセーフ、またはおそらく誰もがそれを意味するだけです:

  1. タイマーを使用している場合は、競合状態を簡単に記述できます。たとえば、この質問を参照してください: タイマー(System.Threading)スレッドセーフティ

  2. あなたのタイマーイベントがトリガとバックあなたを呼び出すことができますタイマー通知のリエントラントあなたが処理を完了するまでの時間最初のイベントを。たとえば、この質問を参照してください:System.Threading.TimerとMonitorを使用したスレッドセーフな実行


Trueは内部でSystem.Timers.Timer使用しSystem.Threading.Timerます。ソースコードを参照してください。
ストーマ

120

彼の著書「CLR Via C#」では、Jeff Ritcherはの使用を推奨していませんSystem.Timers.Timer。このタイマーはから派生しSystem.ComponentModel.Component、Visual Studioのデザイン画面で使用できるようにします。そのため、デザインサーフェイスにタイマーが必要な場合にのみ役立ちます。

彼はSystem.Threading.Timerスレッドプールスレッドのバックグラウンドタスクに使用することを好みます。


36
デザインサーフェイスで使用できます。そうである必要はありません。そうしないことによる悪影響はありません。この質問に対する以前の回答の記事を読んで、Timers.TimerはThreading.Timerよりもはるかに望ましいようです。
Stephen Drew

6
さて、何が好ましいかは、コンテキストに依存しますよね?私が理解しているように、System.Threading.Timerは、渡されたコールバックをThreadPoolからの新しいワーカースレッドで実行します。これは、必ずしもスレッドセーフではない理由でもあると思います。ちょっと理にかなっています。したがって、理論的には、このタイマーがそれを行うため、自分のワーカースレッドをスピンアップする面倒な作業を心配する必要はありません。ちょっとばかげて便利そうです。
Finster 2012年

6
の使用System.Threading.Timerは、スレッドプールの使用や独自のスレッドの作成に似ています。 うちもちろんこれらのクラスはあなたのための同期を処理しません -あなたの仕事ですもの!スレッドプールスレッド、独自のスレッド、タイマーコールバックのいずれもロックを処理しません-どのオブジェクトで、どのような方法でどのような状況でロックする必要があるかは、適切な判断が必要であり、タイマーのスレッドバージョンは最も柔軟性が高く、粒度。
Kirk Woll 2013年

2
-1この回答は最初から主観的または独断的であり、System.Threading.TimerがJeff Ritcherによって好まれる理由に関する具体的な情報を提供していません
ブライアンオグデン

42

これに関するマイクロソフトからの情報(MSDNの備考を参照):

  • System.Timers.Timerは、イベントを発生させ、1つ以上のイベントシンクで定期的にコードを実行します。このクラスは、マルチスレッド環境でサーバーベースまたはサービスコンポーネントとして使用するためのものです。ユーザーインターフェイスがなく、実行時に表示されません。
  • System.Threading.Timerは、スレッドプールスレッドで単一のコールバックメソッドを定期的に実行します。コールバックメソッドは、タイマーがインスタンス化されたときに定義され、変更できません。System.Timers.Timerクラスと同様に、このクラスは、マルチスレッド環境でサーバーベースまたはサービスコンポーネントとして使用するためのものです。ユーザーインターフェイスがなく、実行時に表示されません。
  • System.Windows.Forms.Timer (.NET Frameworkのみ)。イベントを発生させ、1つ以上のイベントシンクのコードを定期的に実行するWindowsフォームコンポーネントです。このコンポーネントにはユーザーインターフェイスがなく、シングルスレッド環境で使用するように設計されています。UIスレッドで実行されます。
  • System.Web.UI.Timer (.NET Frameworkのみ)。非同期または同期のWebページポストバックを定期的に実行するASP.NETコンポーネント。

それは興味深いことです System.Timers.Timer .NET Core 1.0では非推奨でしたが、.NET Core 2.0(/ .NET Standard 2.0)で再び実装された。.NET Standard 2.0の目標は、.NET Frameworkからの切り替えが可能な限り簡単であるということでした。これが、おそらくそれが戻ってきた理由です。

非推奨の場合、.NET Portability Analyzer Visual Studio Add-Inを使用することをお勧めしますSystem.Threading.Timerことを。

System.Threading.Timer以前はマイクロソフトが支持していたようですSystem.Timers.Timer

ノートの編集2018-11-15: .NET Core 1.0に関する古い情報が無効になったため、回答を変更します。



@Taegost、その使用も制限されています。MSDNmsdn.microsoft.com/en-us/library/…を参照し、プラットフォームの可用性に関する備考を読んでください
astrowalker 2016

@astrowalker-そのおかげで、コメントを書いた時点では、この回答の詳細はほとんどありませんでした。お問い合わせの内容になりましたのでコメントを削除しました。
テゴスト、16

1
System.Timers.Timerは、.NET Standard 2.0および.NET Core 2.0以上でサポートされるようになりました。docs.microsoft.com/en-us/dotnet/api/system.timers.timer(記事の最後までスクロール)
Lee Grissom


39

上記で説明されていない重要な違いの1つは、System.Timers.Timer例外を黙って飲み込んでしまうのですが、System.Threading.Timerそうではありません。

例えば:

var timer = new System.Timers.Timer { AutoReset = false };
timer.Elapsed += (sender, args) =>
{
    var z = 0;
    var i = 1 / z;
};
timer.Start();

var timer = new System.Threading.Timer(x =>
{
    var z = 0;
    var i = 1 / z;
}, null, 0, Timeout.Infinite);

1
私は最近、この問題をTimers.Timerでヒットし、非常に苦痛でした... Threading.Timerでどのように書き換えることができるかについてのアイデアはありますか?stackoverflow.com/questions/41618324/…–
Tez Wingfield、

7
ソースコードに空のキャッチがあります。参照してくださいここでSystem.Timers.Timerのソースコードを
stomy

MSプログラマが同じことを本当に同じようにできないのはなぜですか?
xmedeko 2018年

2
例では、一方がどのように例外を飲み込み、もう一方がそうでないかを説明していません。誰かが詳細を記入してくれませんか?
ショーン

24

MSDNから短い比較を見つけました

.NET Frameworkクラスライブラリには、Timerという名前の4つのクラスが含まれ、それぞれが異なる機能を提供します。

System.Timers.Timer、イベントを発生させ、1つ以上のイベントシンクのコードを定期的に実行します。このクラスは、マルチスレッド環境でサーバーベースまたはサービスコンポーネントとして使用するためのものです。ユーザーインターフェイスがなく、実行時に表示されません。

System.Threading.Timer、スレッドプールスレッドで単一のコールバックメソッドを定期的に実行します。コールバックメソッドは、タイマーがインスタンス化されたときに定義され、変更できません。System.Timers.Timerクラスと同様に、このクラスは、マルチスレッド環境でサーバーベースまたはサービスコンポーネントとして使用するためのものです。ユーザーインターフェイスがなく、実行時に表示されません。

System.Windows.Forms.Timer、イベントを発生させ、1つ以上のイベントシンクで定期的にコードを実行するWindowsフォームコンポーネント。このコンポーネントにはユーザーインターフェースがなく、シングルスレッド環境で使用するように設計されています。

System.Web.UI.Timer、定期的間隔で非同期または同期のWebページポストバックを実行するASP.NETコンポーネント。


1

2つのクラスは機能的には同等ですSystem.Timers.Timerが、SynchronizingObjectを設定することにより、ISynchronizeInvokeを介してすべてのタイマー期限切れコールバックを呼び出すオプションがあります。それ以外の場合、両方のタイマーがスレッドプールスレッドで期限切れコールバックを呼び出します。

System.Timers.TimerWindowsフォームデザインサーフェイスにドラッグすると、Visual StudioはSynchronizingObjectをフォームオブジェクトに設定します。これにより、すべての有効期限コールバックがUIスレッドで呼び出されます。


1

MSDNから:System.Threading.Timerコールバックメソッドを使用するシンプルで軽量なタイマーで、スレッドプールスレッドによって提供されます。そのコールバックはユーザーインターフェイススレッドで発生しないため、Windowsフォームでの使用はお勧めしません。System.Windows.Forms.TimerWindowsフォームで使用するのに適しています。サーバーベースのタイマー機能の場合はSystem.Timers.Timer、イベントを発生させ、追加機能を備えたの使用を検討してください。

ソース

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.