问题
Recently I was having some issues with a singelton class that was lazy initializing a dictionary where a second thread would try to use it before it had actually been populated. So I implemented the variable initialization through the Lazy<T> class.
Here is my code:
private static Dictionary<string, string> GroupDefaults
{
get { return mGroupDefaults.Value; }
}
private static Lazy<Dictionary<string, string>> mGroupDefaults =
new Lazy<Dictionary<string,string>>(delegate
{
Dictionary<string, string> defaults = new Dictionary<string, string>();
foreach (KeyValuePair<string, UnitGroup> groupDef in Groups)
defaults.Add(groupDef.Key, groupDef.Value.First().Key);
return defaults;
});
This fixed the problem and now I am considering making this a regular practice of mine to use the Lazy<T>
class anywhere I do lazy initialization to avoid any possible threading issues. So basically I would like to know if this is good/common practice? Or will it be detremental to performance or something?
回答1:
It's pretty hard to say without knowing what type of performance constraints you have, but in my experience, one-time initialization is rarely a bottleneck (since by definition it only occurs once.) Lazy<T>
was written to provide you with this exact service, so I would recommend using it.
回答2:
From the documentation, I find the following:
If no delegate is passed in the Lazy constructor, the wrapped type is created by using Activator.CreateInstance when the value property is first accessed. If the type does not have a default constructor, a run-time exception is thrown.
Activator.CreateInstance
is a method that is notoriously bad for performance. However, that doesn't seem to be a problem in your case, and at any rate, as dlev said, invoking the method once wouldn't be a problem. I haven't seen Lazy<T>
used very often, but I do not see any reason not to use it in your case.
回答3:
If this is for a singleton, a static constructor might be what you want. Something like:
class MySingleton
{
static MySingleton()
{
Instance().InitDict();
}
}
回答4:
I think you may be using Lazy for not it's intended use. Lazy is to be used for situations where something has a large initialization cost, but there is a probable chance that it may not be used during the lifetime of the object.
If you always call GroupDefaults
at least once per it's lifetime a better method would be to initialize GroupDefaults
in a background thread at the start of the container's lifetime and hope that it is done before it is done initializing (I know there is a class for this but I need to dig in to the MSDN to find it)
来源:https://stackoverflow.com/questions/11236855/is-using-lazyt-bad-for-performance