web-dev-qa-db-ja.com

Lazy <>値ファクトリのInvalidOperationException

次のようなものを含むクラスがあります:

public static class Config
{
    private static Lazy<ConfigSource> _cfgSrc = new Lazy<ConfigSource>(
        () => { /* "ValueFactory" here... */ },
        true);

    public static ConfigSource ConfigSource
    {
        get { return _cfgSrc.Value; }
    }
}

ConfigSourceプロパティにアクセスするときに、このInvalidOperationExceptionに遭遇しました:

ValueFactoryがこのインスタンスのValueプロパティにアクセスしようとしました。

Valueプロパティにアクセスする「値ファクトリ」メソッドには何も表示されません。この例外を引き起こしている可能性があるものは他にありますか?この問題は断続的にのみ発生しますが、一度発生すると、IISをリセットして例外を解消します(例外は発生するとキャッシュされるようです)。

38
Jacob

このエラーは、Visual StudioデバッガーでLazy<>Valueプロパティを検査しようとしたときにのみ発生することが判明しました。そうすると、ValueへのアクセスがInvalidOperationExceptionが最終的に発生するまでスレッドを長時間ハングさせているように見えるため、デッドロックが発生するように見えました。元のExceptionを傍受できなかったため、内部のスタックトレースを確認できませんでした。

私はこれをVisual StudioのバグまたはLazy<>の実装としてチョークで示しています。

34
Jacob

ValueFactoryがこのインスタンスのValueプロパティにアクセスしようとしました。

それは誰かを助けるかもしれません、私は私のValueFactoryプロシージャ全体を検査することによってそのエラーを修正することができました。私の例では、単純なモデルを作成して他のデータとリンクしていましたが、リンクプロセス中にシングルトンのValueプロパティにアクセスしていたため、エラーが発生しました。

つまり、ValueFactoryスロー内のLazyオブジェクトの値にアクセスするとなどエラーとなります。エラーメッセージはすでに示しているので;-)

14
Viktor Hofer

これは循環依存関係でも発生しているため、これらの手順を実行しても何も起こらない場合は、スタックトレースを再確認して循環依存関係がないことを確認してください。

12
hermitt

Lazy<T>の動作は、ValueFactory によってスローされた例外をキャッシュすることです。これは、InvalidOperationExceptionメッセージで提供される情報が少ないために、混乱を招く可能性のある動作につながる可能性があります。 MicrosoftはConnect を通じてこの問題を認識していましたが、Wont Fixとマークされているため、問題を診断するのに十分な情報が例外自体にあると感じてください。

受け取るIOEに内部例外がある場合は、続行するのに十分な情報が含まれているはずです(そうするわけではありません)。もう1つの可能性は、例外を再スローするtry...catchブロックがあることです(throw ex;ではなくthrow;)。貴重な情報が失われます。

8
user7116

例外がキャッシュされないようにするには、2番目のパラメーターとして、trueではなくLazyThreadSafetyMode.PublicationOnlyを使用します。

Trueを使用すると、LazyThreadSafetyMode.ExecutionAndPublicationになります。これにより、1つのスレッドのみがValueFactoryメソッドに入ることが保証されますが、例外がキャッシュされることも保証されます。

  private static Lazy<ConfigSource> _cfgSrc = new Lazy<ConfigSource>(
        () => { /* "ValueFactory" here... */ },
        LazyThreadSafetyMode.PublicationOnly);

詳細については、提供されているリンク「sixlettervariables」を参照してください。

6
nicojs

構成を遅延ロードするときは、その構成を必要とするメソッドを呼び出さないようにしてください。これにより、プロセスを最初からやり直す構成ローダーが呼び出され、その結果、説明されたエラーが発生します。

私の場合、ロガーが設定を必要としている間、私は負荷状態をログに記録していました

0
Wouter Vanherck