C# で関数呼び出しをブロックするにはどうすればよいですか?
この関数は、さまざまなクラスから繰り返し呼び出されます。現在の操作を実行するまで、他の誰も使用できないようにロックしたいと考えています。では、またリリースしたいと思います。
助けてください..
ありがとう
編集:私は実際にはスレッドを使用していません...しかし、関数を繰り返し呼び出すタイマーを使用しており、異なるクラス間でも呼び出されます。
を使用しlock
ます。
private static object lockObject = new object();
lock(lockObject) {
// ... code goes here...
}
複数のスレッドからこの関数にアクセスしている場合は、何らかの同期が必要です。
シングルスレッド コードについて話している場合、関数が現在「使用可能」であるかどうかを格納するブール値を使用しないのはなぜですか?
更新:
スレッドを使用していないことを追加したので、IMO は単純な bool で十分です。
さらに状態が必要な場合は、列挙型を作成し、それに応じて設定できます。
スレッドを使用していないと述べています。これが実際に当てはまる場合、コードのブロックが再入可能性を引き起こす可能性のある何かを行わない限り、関数を複数回呼び出すことはできないはずです。
ここでの他の回答の1つがlockステートメントの使用を示唆していることに気付きました。これは、実際の問題が複数のスレッドから関数を呼び出している場合にのみ機能することに注意してください。問題が実際には単一のスレッドを持っているが、関数を再入力する何かを実行している場合 (UI メッセージ キューのポンピングなど)、lock ステートメントはコードの複数回の実行を妨げません。同じスレッドでの再帰的ロック- つまり、異なるスレッドからの同時アクセスのみを禁止します。
したがって、タイマーの使用について言及していることに注意してください。特定の状況は、使用しているタイマーのタイプによって異なります。System.Threading 名前空間のタイマーを使用している場合は、おそらくロックが必要です (このタイマーはスレッドプールを使用してコールバックを実行するため、実際には異なるスレッドでコードを実行しているためです)。ただし、System.Windows.Forms 名前空間のタイマーを使用している場合は、(UI メッセージ キューの処理を介して) UI スレッドを使用して常に実行されるタイマーを使用しています。 have はある種の再入可能性の問題です。
問題が再入可能であり、別のスレッドからコードを呼び出していない場合は、機能しないロックの代わりに、ブール変数を使用して、既に関数内にいるときに記録し、再入を許可しないようにすることができます。 .
そうは言っても、このタイプの再入可能性がある場合は、設計に問題がある可能性があります。
タイマーに関して、以前にトリガーした操作をまだ実行している間に、タイマーが再度トリガーされてもよいかどうかを考慮に入れていない人がいることに注意してください。これを避けるために、私は個人的にタイマーを繰り返しトリガーするように設定することはめったにありません。代わりに、一度だけトリガーするように設定し、トリガーに応答して実行される操作の処理の最後にタイマーを再度有効にします。これは、継続時間 (調整なし) が、最後にトリガーされた操作の処理が終了してから、次にトリガーされた操作が開始されるまでの間隔になることを意味します。
前の操作がまだ完了していないときに同じ操作をトリガーしたくないため、通常はこれが実際に必要なことです。
使用するタイマーによっては、スレッドを使用している場合があります。UI タイマー (Windows.Forms.Timers) は UI スレッドでのみ実行されるため、再入可能に呼び出されることはありません。ただし、System.Threading タイマーはスレッドプール スレッドを使用するため、別のスレッドでコードを再入可能に呼び出すことができます。その場合、スレッドの同期 (ロック) が必要です。
スレッドを使用していない場合、コード自体が呼び出される原因となる何かを実行する場合にのみ、コードを再入可能に呼び出すことができます。明らかなケースはそれ自体を呼び出す場合ですが、それほど明白ではありませんが、何らかのアクションを適用すると一連のイベントが発生し、その結果メソッドが再度呼び出される場合 (「フィードバック ループ」) です。
したがって、最初のステップは、「私のコードは再入可能に呼び出されているか?」と尋ねることです。
2番目のステップは、「なぜ?」と尋ねることです。
次に、コードが再入可能性を引き起こしている場合、「コード自体を呼び出さないようにコードの操作を変更するにはどうすればよいですか」。
または、スレッド化されている場合、「一度に 1 つのスレッドだけがこのコードを実行できるようにするには、どこにロックを配置すればよいでしょうか?」
標準的な方法は、InvalidOperationException をスローして、クラス オブジェクトがまだ使用可能な状態になっていないことをコードのクライアントに通知することです。