Procházet zdrojové kódy

[corlib] Flow CultureInfo from parent thread. Fixes #43193

Marek Safar před 9 roky
rodič
revize
54ea12e4fa

+ 1 - 0
mcs/class/corlib/ReferenceSources/AppContextSwitches.cs

@@ -2,5 +2,6 @@ namespace System {
 	static class AppContextSwitches {
 		public static readonly bool ThrowExceptionIfDisposedCancellationTokenSource = true;
 		public static readonly bool SetActorAsReferenceWhenCopyingClaimsIdentity = false;
+		public static readonly bool NoAsyncCurrentCulture = false;
 	}
 }

+ 36 - 7
mcs/class/corlib/System.Globalization/CultureInfo.cs

@@ -116,6 +116,9 @@ namespace System.Globalization
 		const int CalendarTypeBits = 8;
 
 		const string MSG_READONLY = "This instance is read only";
+
+		static volatile CultureInfo s_DefaultThreadCurrentUICulture;
+		static volatile CultureInfo s_DefaultThreadCurrentCulture;
 		
 		public static CultureInfo InvariantCulture {
 			get {
@@ -128,7 +131,7 @@ namespace System.Globalization
 				return Thread.CurrentThread.CurrentCulture;
 			}
 			set {
-				throw new NotImplementedException ();
+				Thread.CurrentThread.CurrentCulture = value;
 			}
 		}
 
@@ -137,7 +140,7 @@ namespace System.Globalization
 				return Thread.CurrentThread.CurrentUICulture;
 			}
 			set {
-				throw new NotImplementedException ();
+				Thread.CurrentThread.CurrentUICulture = value;
 			}
 		}
 
@@ -511,7 +514,7 @@ namespace System.Globalization
 			}
 		}
 
-		internal void CheckNeutral ()
+		void CheckNeutral ()
 		{
 		}
 
@@ -1070,19 +1073,19 @@ namespace System.Globalization
 		
 		public static CultureInfo DefaultThreadCurrentCulture {
 			get {
-				return Thread.default_culture;
+				return s_DefaultThreadCurrentCulture;
 			}
 			set {
-				Thread.default_culture = value;
+				s_DefaultThreadCurrentCulture = value;
 			}
 		}
 		
 		public static CultureInfo DefaultThreadCurrentUICulture {
 			get {
-				return Thread.default_ui_culture;
+				return s_DefaultThreadCurrentUICulture;
 			}
 			set {
-				Thread.default_ui_culture = value;
+				s_DefaultThreadCurrentUICulture = value;
 			}
 		}
 
@@ -1092,6 +1095,19 @@ namespace System.Globalization
 			}
 		}
 
+		internal static CultureInfo UserDefaultUICulture {
+			get {
+				return ConstructCurrentUICulture ();
+			}
+		}
+
+		internal static CultureInfo UserDefaultCulture {
+			get {
+				return ConstructCurrentCulture ();
+			}
+		}
+
+
 #region reference sources
 		// TODO:
 		internal static readonly bool IsTaiwanSku;
@@ -1144,6 +1160,19 @@ namespace System.Globalization
             return true;
         }
 
+        internal static bool VerifyCultureName(CultureInfo culture, bool throwException) {
+            Contract.Assert(culture!=null, "[CultureInfo.VerifyCultureName]culture!=null");
+
+            //If we have an instance of one of our CultureInfos, the user can't have changed the
+            //name and we know that all names are valid in files.
+            if (!culture.m_isInherited) {
+                return true;
+            }
+
+            return VerifyCultureName(culture.Name, throwException);
+
+        }
+
 #endregion
 	}
 }

+ 0 - 60
mcs/class/corlib/System.Threading/Thread.cs

@@ -122,10 +122,6 @@ namespace System.Threading {
 
 		IPrincipal principal;
 		int principal_version;
-		bool current_culture_set;
-		bool current_ui_culture_set;
-		CultureInfo current_culture;
-		CultureInfo current_ui_culture;
 
 		// the name of current_thread is
 		// important because they are used by the runtime.
@@ -133,9 +129,6 @@ namespace System.Threading {
 		[ThreadStatic]
 		static Thread current_thread;
 
-		static internal CultureInfo default_culture;
-		static internal CultureInfo default_ui_culture;
-
 		// can be both a ThreadStart and a ParameterizedThreadStart
 		private MulticastDelegate m_Delegate;
 
@@ -340,54 +333,6 @@ namespace System.Threading {
 			}
 		}
 
-		//[MethodImplAttribute (MethodImplOptions.InternalCall)]
-		//private static extern int current_lcid ();
-
-		public CultureInfo CurrentCulture {
-			get {
-				CultureInfo culture = current_culture;
-				if (current_culture_set && culture != null)
-					return culture;
-
-				if (default_culture != null)
-					return default_culture;
-
-				current_culture = culture = CultureInfo.ConstructCurrentCulture ();
-				return culture;
-			}
-			
-			[SecurityPermission (SecurityAction.Demand, ControlThread=true)]
-			set {
-				if (value == null)
-					throw new ArgumentNullException ("value");
-
-				value.CheckNeutral ();
-				current_culture = value;
-				current_culture_set = true;
-			}
-		}
-
-		public CultureInfo CurrentUICulture {
-			get {
-				CultureInfo culture = current_ui_culture;
-				if (current_ui_culture_set && culture != null)
-					return culture;
-
-				if (default_ui_culture != null)
-					return default_ui_culture;
-
-				current_ui_culture = culture = CultureInfo.ConstructCurrentUICulture ();
-				return culture;
-			}
-			
-			set {
-				if (value == null)
-					throw new ArgumentNullException ("value");
-				current_ui_culture = value;
-				current_ui_culture_set = true;
-			}
-		}
-
 		public bool IsThreadPoolThread {
 			get {
 				return IsThreadPoolThreadInternal;
@@ -723,11 +668,6 @@ namespace System.Threading {
 			return ManagedThreadId;
 		}
 
-		internal CultureInfo GetCurrentUICultureNoAppX ()
-		{
-			return CultureInfo.CurrentUICulture;
-		}
-
 		[MethodImplAttribute(MethodImplOptions.InternalCall)]
 		internal static extern void GetStackTraces (out Thread[] threads, out object[] stack_frames);
 

+ 21 - 3
mcs/class/corlib/Test/System.Globalization/CultureInfoTest.cs

@@ -12,6 +12,7 @@ using System.Globalization;
 using System.IO;
 using System.Runtime.Serialization.Formatters.Binary;
 using System.Threading;
+using System.Threading.Tasks;
 
 using NUnit.Framework;
 
@@ -727,20 +728,37 @@ namespace MonoTests.System.Globalization
 		}
 
 		[Test]
-		public void DefaultThreadCurrentCultureAndNumberFormaters () {
+		public void DefaultThreadCurrentCultureIsIgnoredWhenCultureFlowsToThread ()
+		{
 			string us_str = null;
 			string br_str = null;
+
 			var thread = new Thread (() => {
 				CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
 				us_str = 100000.ToString ("C");
 				CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("pt-BR");
 				br_str = 100000.ToString ("C");
 			});
+
+			var expected = 100000.ToString ("C");
+
 			thread.Start ();
 			thread.Join ();
 			CultureInfo.DefaultThreadCurrentCulture = null;
-			Assert.AreEqual ("$100,000.00", us_str, "#1");
-			Assert.AreEqual ("R$ 100.000,00", br_str, "#2");
+			Assert.AreEqual (expected, us_str, "#1");
+			Assert.AreEqual (expected, br_str, "#2");
+		}
+
+		[Test]
+		public void FlowCultureInfoFromParentThreadSinceNet46 ()
+		{
+			Func<Task> f = async () => {
+				Thread.CurrentThread.CurrentUICulture = new CultureInfo ("pt-BR");
+				await Task.Yield ();
+				Assert.AreEqual ("pt-BR", Thread.CurrentThread.CurrentUICulture.Name);
+			};
+
+			f ().Wait ();
 		}
 	}
 }

+ 11 - 1
mcs/class/referencesource/mscorlib/system/threading/thread.cs

@@ -1081,7 +1081,6 @@ namespace System.Threading {
 
             dls.Store.SetData(slot, data);
         }
-#if !MONO
 
         // #threadCultureInfo
         //
@@ -1337,12 +1336,23 @@ namespace System.Threading {
         }
 
 #if! FEATURE_LEAK_CULTURE_INFO
+
+#if MONO
+        static void nativeInitCultureAccessors()
+        {
+            m_CurrentCulture = CultureInfo.ConstructCurrentCulture ();
+            m_CurrentUICulture = CultureInfo.ConstructCurrentUICulture ();
+        }
+#else
         [System.Security.SecurityCritical]  // auto-generated
         [ResourceExposure(ResourceScope.None)]
         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
         [SuppressUnmanagedCodeSecurity]
         private static extern void nativeInitCultureAccessors();
 #endif
+#endif
+
+#if !MONO
 
         /*=============================================================*/