この記事では主に、C# でのタイマーの使用とリエントランシーの問題の解決に関する関連知識を紹介します。とても良い参考値です
★前書き
長いことブログを書いていなかったライブライターを開きます。本当に怠け者すぎる。早速、このブログのテーマであるタイマーに直接行きましょう。なぜこれを書いているかというと、数日前に友人から「ハッカー」ガジェットを作るように誘われたからです。その機能は非常に単純で、クリップボードの内容を自動的に取得してメールを送信する必要があります。タイマーを使用してクリップボードの内容をループしますが、電子メールを送信する機能のため、C# を使用した SmtpClient は以前に同様の電子メール送信機能を作成したことがあります。 NetEase を使用できましたが、今は使用できません。何が起こったのかわからないので、あきらめなければなりませんでした。 Timer を使用しているときに、これまで考えもしなかった問題、つまり再入の問題に遭遇しました。
★はじめに
まず、ここで言うタイマーとはSystem.Timers.timerのことを指します。公式の紹介文はここにあり、以下に抜粋します:
Timer コンポーネントは、アプリケーションで Elapsed イベントが発生する定期的な間隔を指定できるサーバーベースのタイマーです。このイベントは、一般的な処理を提供するために処理できます。 たとえば、1 日 24 時間、年中無休で稼働する必要がある重要なサーバーがあるとします。 タイマーを使用してサーバーを定期的にチェックし、システムが稼働していることを確認するサービスを作成できます。 システムが応答しなくなった場合、サービスはサーバーの再起動を試行するか、管理者に通知することができます。 サーバーベースのタイマーは、マルチスレッド環境のセカンダリ スレッドで使用するように設計されています。 サーバー タイマーはスレッド間を移動して発生した Elapsed イベントを処理できるため、Windows タイマーよりも正確な時間にイベントを発生させることができます。
他のタイマーとの違いを知りたい場合は、ここで詳しく紹介されているので、これ以上は言いません(実際、他にもたくさんあるとは知りませんでした)。では、このタイマーを使用するとどのようなメリットがあるのでしょうか?その主な理由は、.NET スレッド プールを通じて実装され、軽量で正確なタイミングを持ち、アプリケーションやメッセージに対する特別な要件がないためです。
★使用方法
以下は、このタイマーの使用方法の簡単な紹介です。実際には、テストのために Microsoft が提供したサンプルを使用し、コードを直接実行しました。動作は以下の通り、タイミングはかなり正確です:
//Timer不要声明成局部变量,否则会被GC回收 private static System.Timers.Timer aTimer; public static void Main() { //实例化Timer类,设置间隔时间为10000毫秒; aTimer = new System.Timers.Timer(10000); //注册计时器的事件 aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent); //设置时间间隔为2秒(2000毫秒),覆盖构造函数设置的间隔 aTimer.Interval = 2000; //设置是执行一次(false)还是一直执行(true),默认为true aTimer.AutoReset = true; //开始计时 aTimer.Enabled = true; Console.WriteLine("按任意键退出程序。"); Console.ReadLine(); } //指定Timer触发的事件 private static void OnTimedEvent(object source, ElapsedEventArgs e) { Console.WriteLine("触发的事件发生在: {0}", e.SignalTime); }
★
リエントランシー問題の再現と分析リエントランシーとは何ですか?これはマルチスレッド プログラミングに関する概念です。プログラム内で複数のスレッドが同時に実行されると、同じメソッドが複数のプロセスによって同時に呼び出される可能性があります。このメソッドにスレッドセーフでないコードが含まれている場合、メソッドの再入によりデータの不整合が発生します。タイマー メソッドの再入とは、1 つのタイマーの処理が完了する前に、時間が経過すると、他のタイマーが処理のためにメソッドに入り続けることを指します。以下は、リエントラント問題の発生を示しています (再現性はあまり良くないかもしれませんが、問題を簡単に説明することもできます):
/* 按任意键退出程序。 触发的事件发生在: 2014/12/26 星期五 23:08:51 触发的事件发生在: 2014/12/26 星期五 23:08:53 触发的事件发生在: 2014/12/26 星期五 23:08:55 触发的事件发生在: 2014/12/26 星期五 23:08:57 触发的事件发生在: 2014/12/26 星期五 23:08:59 */上記の出力は次のように感じますか?結果が奇妙です。最初、スレッド 1 の出力は 1 ですが、これは問題ありません。その後、2 秒後にスレッド 1 が 1 ずつ増加して 2 を出力します。なぜ、スレッド 2 の出力が途中で表示されるのでしょうか。さらに奇妙なのは、スレッド 2 の出力は最初は 1 でしたが、1 ずつ増加すると 3 になったことです。実際、これはリエントランシーによって引き起こされる問題です。心配しないでください。分析後に原因がわかります。
まず、タイマーが計時を開始した後、スレッド 1 の実行メソッドが開始され、スレッド 1 が初めて出力するとき、設定された計時間隔が 1 であるため、スレッド 1 は 2 秒間スリープしません。スレッド 1 が 1 秒間スリープした後、スレッド 2 はスレッド 1 が実行中であるかスリープ中であるかを気にせず、スレッド 2 の実行メソッドを再び開始します。眠っていて、それ自体は増加しません。さらに 1 秒が経過し、同時に 2 つのイベントが発生し、スレッド 1 が休止状態を通過し、自動インクリメント出力が 2 になりました。また、タイマーはスレッド 3 の出力も同時に開始しました。スレッド 1 が自動インクリメントされた後の値は 2 でした。さらに 1 秒後、スレッド 2 はすでに 2 であったため、自動インクリメント後の出力は 3 になりました。問題は、1 つの Timer によって開始されたスレッドの処理が完了していないときに、別の Timer が処理のためにメソッドに入り続けることです。
では、この問題を解決するにはどうすればよいでしょうか?さまざまなシナリオに適応するために 3 つの解決策を 1 つずつ見てみましょう。ただし、より安全な最後の解決策をお勧めします。
★
再入可能問題の解決策1、使用lock(Object)的方法来防止重入,表示一个Timer处理正在执行,下一个Timer发生的时候发现上一个没有执行完就等待执行,适用重入很少出现的场景(具体也没研究过,可能比较占内存吧)。
代码跟上面差不多,在触发的方法中加入lock,这样当线程2进入触发的方法中,发现已经被锁,会等待锁中的代码处理完在执行,代码如下:
private static object locko = new object(); /// <summary> /// System.Timers.Timer的回调方法 /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private static void TimersTimerHandler(object sender, EventArgs args) { int t = ++num; lock (locko) { Console.WriteLine(string.Format("线程{0}输出:{1}, 输出时间:{2}", t, outPut.ToString(), DateTime.Now)); System.Threading.Thread.Sleep(2000); outPut++; Console.WriteLine(string.Format("线程{0}自增1后输出:{1},输出时间:{2}", t, outPut.ToString(), DateTime.Now)); } }
执行结果:
2、设置一个标志,表示一个Timer处理正在执行,下一个Timer发生的时候发现上一个没有执行完就放弃(注意这里是放弃,而不是等待哦,看看执行结果就明白啥意思了)执行,适用重入经常出现的场景。代码如下:
private static int inTimer = 0; /// <summary> /// System.Timers.Timer的回调方法 /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private static void TimersTimerHandler(object sender, EventArgs args) { int t = ++num; if (inTimer == 0) { inTimer = 1; Console.WriteLine(string.Format("线程{0}输出:{1}, 输出时间:{2}", t, outPut.ToString(), DateTime.Now)); System.Threading.Thread.Sleep(2000); outPut++; Console.WriteLine(string.Format("线程{0}自增1后输出:{1},输出时间:{2}", t, outPut.ToString(), DateTime.Now)); inTimer = 0; } }
执行结果:
3、在多线程下给inTimer赋值不够安全,Interlocked.Exchange提供了一种轻量级的线程安全的给对象赋值的方法(感觉比较高上大,也是比较推荐的一种方法),执行结果与方法2一样,也是放弃执行。Interlocked.Exchange用法参考这里。
private static int inTimer = 0; /// <summary> /// System.Timers.Timer的回调方法 /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private static void TimersTimerHandler(object sender, EventArgs args) { int t = ++num; if (Interlocked.Exchange(ref inTimer, 1) == 0) { Console.WriteLine(string.Format("线程{0}输出:{1}, 输出时间:{2}", t, outPut.ToString(), DateTime.Now)); System.Threading.Thread.Sleep(2000); outPut++; Console.WriteLine(string.Format("线程{0}自增1后输出:{1},输出时间:{2}", t, outPut.ToString(), DateTime.Now)); Interlocked.Exchange(ref inTimer, 0); } }
执行结果:
★总结
终于码完字了,真心不容易啊。写博客是个挺耗精力的事情,真心佩服那些大牛们笔耕不辍,致敬!在这里稍微总结一下,timer是一个使用挺简单的类,拿来即用,这里主要总结了使用timer时重入问题的解决,以前也没思考过这个问题,解决方案也挺简单,在这里列出了三种,不知道还有没有其他的方式。这里的解决方案同时也适用多线程的重入问题。
以上がC# でのタイマーの使用法と再入可能の問題の解決方法の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

C#は、Microsoftによって開発された最新のオブジェクト指向プログラミング言語であり、.NETフレームワークの一部として開発されています。 1.C#は、カプセル化、継承、多型を含むオブジェクト指向プログラミング(OOP)をサポートしています。 2。C#の非同期プログラミングは非同期を通じて実装され、適用応答性を向上させるためにキーワードを待ちます。 3. LINQを使用してデータ収集を簡潔に処理します。 4.一般的なエラーには、null参照の例外と、範囲外の例外インデックスが含まれます。デバッグスキルには、デバッガーと例外処理の使用が含まれます。 5.パフォーマンスの最適化には、StringBuilderの使用と、不必要な梱包とボクシングの回避が含まれます。

C#.NETアプリケーションのテスト戦略には、ユニットテスト、統合テスト、エンドツーエンドテストが含まれます。 1.単位テストにより、コードの最小ユニットがMSTEST、ヌニット、またはXUNITフレームワークを使用して独立して動作することを保証します。 2。統合テストでは、一般的に使用されるシミュレートされたデータと外部サービスを組み合わせた複数のユニットの機能を検証します。 3.エンドツーエンドのテストでは、ユーザーの完全な操作プロセスをシミュレートし、通常、セレンは自動テストに使用されます。

C#シニア開発者とのインタビューでは、非同期プログラミング、LINQ、.NETフレームワークの内部作業原則などのコア知識をマスターする必要があります。 1.非同期プログラミングは、非同期を通じて操作を簡素化し、アプリケーションの応答性を向上させるのを待ちます。 2.LinqはSQLスタイルでデータを操作し、パフォーマンスに注意を払います。 3.ネットフレームワークのCLRはメモリを管理し、ガベージコレクションに注意して使用する必要があります。

C#.NETインタビューの質問と回答には、基本的な知識、コアの概念、高度な使用が含まれます。 1)基本知識:C#は、Microsoftが開発したオブジェクト指向言語であり、主に.NETフレームワークで使用されています。 2)コアの概念:委任とイベントは動的な結合方法を可能にし、LINQは強力なクエリ関数を提供します。 3)高度な使用:非同期プログラミングは応答性を向上させ、式ツリーは動的コード構造に使用されます。

C#.NETは、その強力なエコシステムと豊富なサポートのため、マイクロサービスを構築するために人気のある選択肢です。 1)asp.netcoreを使用してRestfulapiを作成して、順序の作成とクエリを処理します。 2)GRPCを使用して、マイクロサービス間の効率的な通信を実現し、注文サービスを定義および実装します。 3)Dockerコンテナ化されたマイクロサービスを介して展開と管理を簡素化します。

C#および.NETのセキュリティベストプラクティスには、入力検証、出力エンコード、例外処理、認証と承認が含まれます。 1)正規表現または組み込みのメソッドを使用して入力を検証して、悪意のあるデータがシステムに入るのを防ぎます。 2)XSS攻撃を防ぐための出力エンコード、httputility.htmlencodeメソッドを使用します。 3)例外処理により、情報の漏れが回避され、エラーが記録されますが、詳細情報はユーザーに返されません。 4)ASP.Netidentityおよび請求に基づく許可を使用して、不正アクセスから申請を保護します。

C言語におけるコロン( ':')の意味:条件付きステートメント:条件付き式とステートメントの分離ブロックループステートメント:初期化、条件付きおよび増分式のマクロ定義の分離:マクロ名とマクロ値の分離単一行コメント:コメントアレイの寸法としてのコロンから行までのコンテンツを表す:アレイの寸法を指定する

c言語は、後の運動後演算子であり、その動作メカニズムには次のものが含まれます。最初に変数の値を取得します。 aの値を1 x1。増加した後、aの値を返します。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

SublimeText3 Linux 新バージョン
SublimeText3 Linux 最新バージョン

WebStorm Mac版
便利なJavaScript開発ツール

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

AtomエディタMac版ダウンロード
最も人気のあるオープンソースエディター
