3

我们有一个 .net 3.5 多线程 Windows 窗体应用程序。正在启动 4-5 个后台工作人员/异步调用来检索数据。大约 10 次中的 1 次,其中一个线程会引发以下错误。有时错误是空异常,而是相同的调用堆栈。我们已将问题追溯到以某种方式丢失其 CultureInfo 的线程。还有其他人遇到过这个吗?

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)
4

4 回答 4

1

CultureInfo.DefaultThreadCurrentCulture尝试使用和/或为整个域使用默认文化CultureInfo.DefaultThreadCurrentUICulture,看看是否有帮助。总而言之,您将能够确保它是否与线程的文化有关

UPD :在值类型lock上使用同步方法(如,Monitor等)时可能会引发特定异常,对同步方法的调用将框值,每次都创建一个新值。我怀疑它可能是框架中的此类严重错误。

你能检查你的同步代码吗?

UPD2:好的,让我们尝试调试

之后,很有可能为您的问题找到解决方法/解决方案

于 2013-04-19T21:01:15.717 回答
1

从调用堆栈来看,这似乎是一个框架错误(某种)。StreamWriter 构造函数似乎正在通过一系列复杂的调用执行非线程安全操作(访问 GetCultureTableRecord)。我的建议是序列化您对 StreamWriter 构造函数的调用:

// Put this somewhere convenient
public static Object swConstructorLock = new Object();

然后,当您创建 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);
}
于 2013-04-19T21:27:30.813 回答
1

我发现每个 Web 请求都会调用 CultureInfo.ClearCachedData :/ 删除它可以解决问题。似乎 Culture 仍然需要某种锁,因为线程 A 调用 ClearCachedData 并且线程 B 请求数据并且它抛出了一个空异常。

于 2013-04-21T18:25:25.437 回答
0

我在 .NET 3.5 应用程序中也遇到了这个异常(一次,出乎意料):

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)

这发生在锁定部分,但锁定不是值类型。

于 2015-05-30T02:21:35.863 回答