I have a class containing something like the following:
public static class Config
{
private static Lazy<ConfigSource> _cfgSrc = new Lazy<ConfigSource>(
() => { /* "ValueFactory" here... */ },
true);
public static ConfigSource ConfigSource
{
get { return _cfgSrc.Value; }
}
}
In accessing the ConfigSource
property, I encountered this InvalidOperationException
:
ValueFactory attempted to access the Value property of this instance.
I don't see anything in my "value factory" method that accesses the Value
property. Is there anything else that could be triggering this exception? This problem only happens intermittently, but once it does, it takes resetting IIS to clear up the Exception (which appears to be cached once it occurs).
It turned out that this error only occurred when trying to inspect the Value
property of the Lazy<>
in the Visual Studio debugger. Doing so appeared to create a deadlock because the accessing of Value
then seemed to hang the thread for a long time until the InvalidOperationException
finally occurred. I could never intercept the original Exception
, so I couldn't see the inner stacktrace.
I'm just chalking this up as a bug in Visual Studio or their implementation of Lazy<>
.
ValueFactory attempted to access the Value property of this instance.
It may help somebody, I was able to fix that error by inspecting my entire ValueFactory procedure.
In my example, I was creating a simple model and the linked it with some other data but during the linking process I was accessing the Value property in a singleton and that caused the error.
So accessing the Value of a Lazy object inside the ValueFactory throws such an error.
As the error message is already indicating ;-)
This has also happened to me with circular dependencies, so if these steps lead you nowhere, try double checking the stacktrace and verifying that there are no circular dependencies.
The behavior of Lazy<T>
is to cache exceptions thrown by the ValueFactory
. This can lead to potentially confusing behavior due to the paucity of information given in the InvalidOperationException
message. Microsoft was made aware of this issue through Connect, however, it is marked as Wont Fix as they feel there is enough information in the exception itself to diagnose the problem.
If there is an inner exception for the IOE you receive, it should (not saying it will) contain enough information to continue onwards. Another possibility is you have a try...catch
blocks which rethrows exceptions (throw ex;
instead of throw;
), you will lose valuable information.
To make sure your exception isn't cached, use LazyThreadSafetyMode.PublicationOnly as a second parameter, instead of true.
Using true, you'll end up with a LazyThreadSafetyMode.ExecutionAndPublication. This will ensure only one thread enteres the ValueFactory method, but also ensures exceptions will be cached.
private static Lazy<ConfigSource> _cfgSrc = new Lazy<ConfigSource>(
() => { /* "ValueFactory" here... */ },
LazyThreadSafetyMode.PublicationOnly);
See the link sixlettervariables provided for more information.