CultureInfo thread safety

2020-08-13 07:47发布

问题:

I have a multi-threaded application which parses some text and it needs to use English Culture Info for parsing numbers from this text. So, i do not want to create EngCulture everytime i call the parsing function. Currently i am passing EngCulture as a parameter but i am not happy with this. I want to define the EngCulture as a static member so it will be shared by threads.

Msdn documentation says that "Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe." I am just using the following function, so how could i know whether TryParse uses any instance members of the EngCulture or not?

public static CultureInfo EngCulture = new CultureInfo("en-US", false);

void parser()
{
    if (int.TryParse(value, NumberStyles.Number, EngCulture, out num))...
}

回答1:

Try to use CultureInfo.GetCultureInfo("en-US") that "retrieves a cached, read-only instance of a culture using the specified culture name."

http://msdn.microsoft.com/en-us/library/yck8b540.aspx

or make your field to be readonly so you will not need a lock:

private static CultureInfo _culture = CultureInfo.ReadOnly(new CultureInfo("en-US"));


回答2:

In order to get thread-safety you can create a read-only culture using the static CultureInfo.ReadOnly method:

public static CultureInfo EngCulture = CultureInfo.ReadOnly(
    new CultureInfo("en-US", false));


回答3:

You can set the CultureInfo of a specific Thread with System.Threading.Thread.CurrentThread.CurrentCulture = myCI; so you do not have to pass it every time you call a function.

Note that just accessing getters from multiple threads won't do any harm in most cases if you do not modify the object.



回答4:

"Members" means methods plus operators plus fields plus properties. You are using an instance member and so should use a lock or find an alternative way of doing this.

Hope that helps!



回答5:

Two points:

i do not want to create EngCulture everytime i call the parsing function

I don't think this would actually be too much of a concern - CultureInfos aren't going to be especially large, and as for performance, the 'built-in' ones are actually cached, so all a new does is retrieve an existing object. By all means profile and see if it is actually a problem...

how could i know whether TryParse uses any instance members of the EngCulture or not?

I'd be extremely surprised to discover a method that accepted a CultureInfo and then went on to change that CultureInfo in any way. Although they aren't actually formally immutable, I would use them (especially the 'built-in' ones) as if they were immutable, without a second thought.

So, I would say have a static new CultureInfo("en-US", false) and pass it around - nothing is going to mutate it, so multi-threading issues don't arise.