昨日、使用している単純なキャッシュ オブジェクトにマルチスレッドの問題があることを発見しました。
If Dictionary.Contains(lsKey.ToLower) Then 'if rate cached, then return value
lvResult = Dictionary.Item(lsKey.ToLower)
Else 'else retrieve from database, store, and return value
lvResult = GetRateFromDB(voADO,
veRateType,
vdEffDate)
Dictionary.Add(lsKey.ToLower, lvResult)
End If
この問題は、asp.net Web サイトで発見されました。エラーメッセージは、「既に存在するハッシュテーブルに値を追加しようとしています。上記のコードからわかるように、これが発生する可能性は間違いなく終了します。私はウェイトハンドルにある程度精通しており、それらが問題を解決すると考えていました。 .だから私はクラスレベルで私のwaithandleを宣言しました:
private Shared _waitHandle as new AutoResetEvent(True)
次に、問題のあるコードの特定のセクションで:
_waitHandle.Wait()
If Dictionary.Contains(lsKey.ToLower) Then 'if rate cached, then return value
lvResult = Dictionary.Item(lsKey.ToLower)
Else 'else retrieve from database, store, and return value
lvResult = GetRateFromDB(voADO,
veRateType,
vdEffDate)
Dictionary.Add(lsKey.ToLower, lvResult)
End If
_waitHandle.Set()
何らかの理由で、上記の次のコードは常にブロックされていました。最初のスレッドでさえ、コードにアクセスしました。私はしばらく物事をいじり、コンストラクターで待機ハンドルをシグナル状態に設定しようとしましたが、それを機能させることはできませんでした。
私は代わりに次のものを使用することになりますが、これは正常に機能します。
SyncLock loLock
If Dictionary.Contains(lsKey.ToLower) Then 'if rate cached, then return value
lvResult = Dictionary.Item(lsKey.ToLower)
Else 'else retrieve from database, store, and return value
lvResult = GetRateFromDB(voADO,
veRateType,
vdEffDate)
Dictionary.Add(lsKey.ToLower, lvResult)
End If
End SyncLock
だから私は2つの質問があります:
- waithandle ソリューションが機能しなかったのはなぜですか?
- SynLock は、この場合に使用する正しい/最適化されたロック タイプですか?