C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[1]: ロックがかかっている場合待たずに処理をスキップ


(過去ログ 178 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■102252 / inTopicNo.1)  ロックがかかっている場合待たずに処理をスキップ
  
□投稿者/ kiku (366回)-(2023/08/04(Fri) 10:15:31)

分類:[C#] 

2023/08/04(Fri) 10:21:01 編集(投稿者)
2023/08/04(Fri) 10:17:01 編集(投稿者)

<pre><pre>ロックがかかっている場合に、
待たずに処理をスキップしたいのですが、
方法がわかりません。
どんな方法があるでしょうか?

環境
・WinFormアプリ
・.NETFrameWork4.8
・C#

private readonly object lockobject = new object();

スレッドA
 lock (lockobject)
 {
  処理A
 }

スレッドB
 lock (lockobject)
 {
  処理B
 }

スレッドC
・ロックがかかっていたら、待たずに終了 <===●ここがわからない
・ロックがかかっていなかったら、下記をしたい。
 lock (lockobject)
 {
  処理C
 }
</pre></pre>
引用返信 編集キー/
■102253 / inTopicNo.2)  Re[1]: ロックがかかっている場合待たずに処理をスキップ
□投稿者/ 魔界の仮面弁士 (3676回)-(2023/08/04(Fri) 10:37:32)
2023/08/04(Fri) 10:50:17 編集(投稿者)

No102252 (kiku さん) に返信
> ロックがかかっている場合に、
> 待たずに処理をスキップしたいのですが、

lock ステートメントでは無く、ロック取得時にタイムアウト時間を
指定できるメソッドを試してみてください。

たとえば「ReaderWriterLockSlim クラス」を使ってみるのは如何でしょう。

このクラスは、
 未入力
 読取状態
 更新状態
 書込状態
の 4 状態を持っており、読み書きでロックが分かれていることで
デッドロックしにくい設計になっています。
(その分、単純 lock よりも若干遅くなります)

使う時は、TryEnter何某Lock でロックを取得、Exit何某Lock でロック解除です。
TryEnter{Read|Write|UpgradeableRead}Lock メソッドの引数には
タイムアウトを時間を指定できます。


「ReaderWriterLockSlim クラス」以外にも、
「ReaderWriterLock クラス」というものがあります。

こちらは、書き込みは単一、読取りは複数の場合に使われるもので、
ロック取得時のタイムアウト時間を指定できるようになっています。


そのほか、「Monitor クラス」を使ってみることもできます。
このクラスの TryEnter メソッドでタイムアウト時間を指定できます。

ちなみにこの Monitor クラスは、C# の lock ステートメントの
内部処理でも使われています。lock ステートメントでは、
タイムアウト指定のない Enter メソッドが呼ばれるだけですけれどね。
https://ufcpp.net/study/csharp/sp_thread.html#dotnet4
引用返信 編集キー/
■102254 / inTopicNo.3)  Re[2]: ロックがかかっている場合待たずに処理をスキップ
□投稿者/ kiku (367回)-(2023/08/04(Fri) 11:13:16)
No102253 (魔界の仮面弁士 さん) に返信
> 2023/08/04(Fri) 10:50:17 編集(投稿者)
>
> ■No102252 (kiku さん) に返信
>>ロックがかかっている場合に、
>>待たずに処理をスキップしたいのですが、
> たとえば「ReaderWriterLockSlim クラス」を使ってみるのは如何でしょう。

返答ありがとうございます。

今回は状態は利用しないため、write状態を使った場合には
下記のようなイメージですね。

スレッドA
 TryEnterWriteLock(タイムアウト無限)
 ExitWriteLock

スレッドC
 try{
  var ret = false
  ret = TryEnterWriteLock(タイムアウト0);
  if(ret){
   処置C
  }else{
   ロックが取得できないため、何もしない。
  }
 }finnaly{
  if(ret){
   ExitWriteLock();
  }
 }

> ちなみにこの Monitor クラスは、C# の lock ステートメントの
> 内部処理でも使われています。lock ステートメントでは、
> タイムアウト指定のない Enter メソッドが呼ばれるだけですけれどね。
> https://ufcpp.net/study/csharp/sp_thread.html#dotnet4

行き違いになってしまいましたが、
コメント書いてしまったので、そのまま書きます。

ReaderWriterLockSlimを利用する案を頂いたため、
自分でも更に調査してみました。
Monitor.TryEnterが使いそうと思ました。
この方法なら、既存のlock文はそのまま使えると
思ったのですが、どうでしょうか?

private readonly object lockobject = new object();

スレッドA
 lock (lockobject)
 {
  処理A
 }

スレッドB
 lock (lockobject)
 {
  処理B
 }

スレッドC
 var timeout = TimeSpan.FromMilliseconds(0);<==待たない
 bool lockTaken = false;
 try {
  Monitor.TryEnter(lockobject, timeout, ref lockTaken);
  if (lockTaken) {
  処理C
  }
  else {
  ロックが取得できないので、何もしない。
  }
 }
 finally {
  if (lockTaken) {
  Monitor.Exit(lockObj);
  }
 }

引用返信 編集キー/
■102255 / inTopicNo.4)  Re[1]: ロックがかかっている場合待たずに処理をスキップ
□投稿者/ furu (214回)-(2023/08/04(Fri) 11:49:31)
No102252 (kiku さん) に返信
> どんな方法があるでしょうか?
System.Threading.Monitorというのもありますね。
使ったことないし、以下も未テストです。

private readonly object lockobject = new object();

スレッドA
 Monitor.Enter(lockobject);
 処理A
 Monitor.Exit(lockobject);

スレッドB
 Monitor.Enter(lockobject);
 処理B
 Monitor.Exit(lockobject);

スレッドC
 if (Monitor.TryEnter(lockobject))
 {
  処理C
  Monitor.Exit(lockobject);
 }

引用返信 編集キー/
■102256 / inTopicNo.5)  Re[3]: ロックがかかっている場合待たずに処理をスキップ
□投稿者/ 魔界の仮面弁士 (3677回)-(2023/08/04(Fri) 13:26:18)
No102254 (kiku さん) に返信
>  var timeout = TimeSpan.FromMilliseconds(0);<==待たない
そういう時は、TimSpan.Zero を使います。

ただし、Monitor クラスで即時タイムアウトを目的とする場合には、
 void TryEnter(object, TimeSpan, ref bool)
 bool TryEnter(object, TimeSpan)
 void TryEnter(object, int, ref bool)
 bool TryEnter(object, int)
ではなく、
 void TryEnter(object, ref bool)
 bool TryEnter(object)
を使えば充分です。

ちなみに
 void Enter(object, ref bool)
 bool Enter(object)
は無限待機ですね。

 
 
> この方法なら、既存のlock文はそのまま使えると
> 思ったのですが、どうでしょうか?
lockobject のロック操作が lock と Monitor の併用ということになると、
処理記述に対称性がなくなるので、後からソースコードを読むときに分かりにくくなるかも。


しかしそれ以前の問題として、
> Monitor.TryEnter(lockobject, timeout, ref lockTaken);
> Monitor.Exit(lockObj);
Enter 時は「lockobject」で、
Exit 時は「lockObj」というのは、流石に問題がありそう。
引用返信 編集キー/
■102257 / inTopicNo.6)  Re[4]: ロックがかかっている場合待たずに処理をスキップ
□投稿者/ kiku (368回)-(2023/08/04(Fri) 16:17:10)
No102256 (魔界の仮面弁士 さん) に返信
> ■No102254 (kiku さん) に返信
>> var timeout = TimeSpan.FromMilliseconds(0);<==待たない
> そういう時は、TimSpan.Zero を使います。

ご指摘ありがとうございます。

> ちなみに
>  void Enter(object, ref bool)
>  bool Enter(object)
> は無限待機ですね。

ご指摘ありがとうございます。

>>この方法なら、既存のlock文はそのまま使えると
>>思ったのですが、どうでしょうか?
> lockobject のロック操作が lock と Monitor の併用ということになると、
> 処理記述に対称性がなくなるので、後からソースコードを読むときに分かりにくくなるかも。

ご指摘ありがとうございます。

> しかしそれ以前の問題として、
>>Monitor.TryEnter(lockobject, timeout, ref lockTaken);
>>Monitor.Exit(lockObj);
> Enter 時は「lockobject」で、
> Exit 時は「lockObj」というのは、流石に問題がありそう。

これは記述ミスですね。
スルーしてください。

>> どんな方法があるでしょうか?
>System.Threading.Monitorというのもありますね。
>使ったことないし、以下も未テストです。

furuさん、アドバイスありがとうございます。

解決としてクローズします。
ありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -