Reputation: 7318
We have a .net 3.5 multi-threaded windows forms application. Is is launching 4-5 background workers/ async calls to retrieve data. About 1 in 10 times, one of the threads throws the following error. Sometimes the error is a null exception instead but the same exact call stack. We have tracked the issue down to the thread somehow losing its CultureInfo. Anyone else ran into this?
System.Threading.SynchronizationLockException: Object synchronization method was called from an unsynchronized block of code.
at System.Globalization.CultureTableRecord.GetCultureTableRecord(String name, Boolean useUserOverride)
at System.Globalization.CultureTableRecord.GetCultureTableRecord(Int32 cultureId, Boolean useUserOverride)
at System.Globalization.CultureInfo..ctor(Int32 culture, Boolean useUserOverride)
at System.Globalization.CultureInfo.GetCultureByLCIDOrName(Int32 preferLCID, String fallbackToString)
at System.Globalization.CultureInfo.InitUserDefaultUICulture()
at System.Globalization.CultureInfo.get_UserDefaultUICulture()
at System.Threading.Thread.get_CurrentUICulture()
at System.Resources.ResourceManager.GetString(String name, CultureInfo culture)
at System.Environment.ResourceHelper.GetResourceStringCode(Object userDataIn)
at System.Environment.GetResourceFromDefault(String key)
at System.Diagnostics.StackTrace.ToString(TraceFormat traceFormat)
at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.IO.StreamWriter.Init(Stream stream, Encoding encoding, Int32 bufferSize)
at System.IO.StreamWriter..ctor(Stream stream, Encoding encoding, Int32 bufferSize)
at System.Web.Services.Protocols.SoapHttpClientProtocol.GetWriterForMessage(SoapClientMessage message, Int32 bufferSize)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Serialize(SoapClientMessage message)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
Upvotes: 3
Views: 890
Reputation: 1870
I got this exception (once, out of a blue), also in a .NET 3.5 app:
System.Threading.SynchronizationLockException: Object synchronization method was called from an unsynchronized block of code.
at System.Globalization.CultureTableRecord.GetCultureTableRecord(String name, Boolean useUserOverride)
at System.Globalization.CultureTableRecord.GetCultureTableRecord(Int32 cultureId, Boolean useUserOverride)
at System.Globalization.CultureInfo..ctor(Int32 culture, Boolean useUserOverride)
at System.Globalization.CultureInfo.GetCultureByLCIDOrName(Int32 preferLCID, String fallbackToString)
at System.Globalization.CultureInfo.InitUserDefaultCulture()
at System.Globalization.CultureInfo.get_UserDefaultCulture()
at System.Threading.Thread.get_CurrentCulture()
at System.Globalization.DateTimeFormatInfo.get_CurrentInfo()
at System.DateTime.ToString(String format)
This happened in a locked section, but the lock was not a value type.
Upvotes: 0
Reputation: 7318
I found that CultureInfo.ClearCachedData was being called on every web request :/ Removing that fixed the issue. There seems that Culture still needs some sort of lock since thread A calls ClearCachedData and thread B requests the data and it throws a null exception.
Upvotes: 1
Reputation: 51359
From just looking at the call stack, this appears to be a framework bug (of sorts). It seems that the StreamWriter constructor is performing a non-thread-safe operation (accessing GetCultureTableRecord) through a complex series of calls. My recommendation would be to serialize your calls to the StreamWriter constructor:
// Put this somewhere convenient
public static Object swConstructorLock = new Object();
then, when you create your StreamWriters:
// Lock this constructor because it does something that isnt thread-safe as per http://stackoverflow.com/questions/16113366/windows-forms-threads-are-losing-their-culture
StreamWriter myStreamWriter;
lock (swConstructorLock) {
myStreamWriter = new StreamWriter(theStreamToWrite);
}
Upvotes: 1
Reputation: 8244
Try playing with default culture for entire domain using CultureInfo.DefaultThreadCurrentCulture
and/or CultureInfo.DefaultThreadCurrentUICulture
and see if that helps. All in all, you'll be able to ensure whether it's related to thread's culture
UPD: that specific exception may be thrown when using sync methods like lock
, Monitor
, etc on value types, calls to sync methods will box value, creating new one every time. I doubt it could be such serios bug in framework.
Can you check your synchronization code?
UPD2: ok, let's try to debug.
First off, turn on break on every exception thrown
Next, enable .NET Framework debugging that will help you to locate an error
After that, there is a high chance for a workaround/solution for you problem
Upvotes: 1