2 // System.Threading.Thread.cs
5 // Dick Porter (dick@ximian.com)
7 // (C) Ximian, Inc. http://www.ximian.com
8 // Copyright (C) 2004-2006 Novell, Inc (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Runtime.Remoting.Contexts;
31 using System.Runtime.Serialization;
32 using System.Runtime.Serialization.Formatters.Binary;
33 using System.Security.Permissions;
34 using System.Security.Principal;
35 using System.Globalization;
36 using System.Runtime.CompilerServices;
37 using System.Runtime.InteropServices;
39 using System.Collections.Generic;
40 using System.Reflection;
41 using System.Security;
42 using System.Runtime.ConstrainedExecution;
44 namespace System.Threading {
45 [StructLayout (LayoutKind.Sequential)]
46 sealed class InternalThread : CriticalFinalizerObject {
47 #pragma warning disable 169, 414, 649
48 #region Sync with metadata/object-internals.h
50 // stores a thread handle
51 internal IntPtr system_thread_handle;
53 /* Note this is an opaque object (an array), not a CultureInfo */
54 private object cached_culture_info;
55 /* accessed only from unmanaged code */
58 private ThreadState state;
59 private object abort_exc;
60 private int abort_state_handle;
61 /* thread_id is only accessed from unmanaged code */
62 internal Int64 thread_id;
64 /* start_notify is used by the runtime to signal that Start()
67 private IntPtr start_notify;
68 private IntPtr stack_ptr;
69 private UIntPtr static_data; /* GC-tracked */
70 private IntPtr runtime_thread_info;
71 /* current System.Runtime.Remoting.Contexts.Context instance
72 keep as an object to avoid triggering its class constructor when not needed */
73 private object current_appcontext;
74 private object pending_exception;
75 private object root_domain_thread;
76 internal byte[] _serialized_principal;
77 internal int _serialized_principal_version;
78 private IntPtr appdomain_refs;
79 private int interruption_requested;
80 private IntPtr synch_cs;
81 internal bool threadpool_thread;
82 private bool thread_interrupt_requested;
83 /* These are used from managed code */
84 internal int stack_size;
85 internal byte apartment_state;
86 internal volatile int critical_region_level;
87 internal int managed_id;
89 private IntPtr manage_callback;
90 private IntPtr interrupt_on_stop;
92 private IntPtr thread_pinning_ref;
93 private IntPtr async_invoke_method;
95 * These fields are used to avoid having to increment corlib versions
96 * when a new field is added to the unmanaged MonoThread structure.
98 private IntPtr unused1;
99 private IntPtr unused2;
101 #pragma warning restore 169, 414, 649
103 // Closes the system thread handle
104 [MethodImplAttribute(MethodImplOptions.InternalCall)]
105 private extern void Thread_free_internal(IntPtr handle);
107 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
109 Thread_free_internal(system_thread_handle);
113 [StructLayout (LayoutKind.Sequential)]
114 public sealed partial class Thread {
115 #pragma warning disable 414
116 #region Sync with metadata/object-internals.h
117 private InternalThread internal_thread;
118 object m_ThreadStartArg;
119 private ExecutionContext ec_to_set;
121 #pragma warning restore 414
123 IPrincipal principal;
124 int principal_version;
125 bool current_culture_set;
126 bool current_ui_culture_set;
127 CultureInfo current_culture;
128 CultureInfo current_ui_culture;
130 // the name of local_slots, current_thread and _ec is
131 // important because they are used by the runtime.
133 static object[] local_slots;
136 static Thread current_thread;
138 /* The actual ExecutionContext of the thread. It's
139 ThreadStatic so that it's not shared between
142 static ExecutionContext _ec;
144 static internal CultureInfo default_culture;
145 static internal CultureInfo default_ui_culture;
147 // can be both a ThreadStart and a ParameterizedThreadStart
148 private MulticastDelegate m_Delegate;
149 //private string thread_name=null;
151 [MethodImplAttribute(MethodImplOptions.InternalCall)]
152 private extern void ConstructInternalThread ();
154 private InternalThread Internal {
156 if (internal_thread == null)
157 ConstructInternalThread ();
158 return internal_thread;
162 public static Context CurrentContext {
163 [SecurityPermission (SecurityAction.LinkDemand, Infrastructure=true)]
165 return(AppDomain.InternalGetContext ());
170 * These two methods return an array in the target
171 * domain with the same content as the argument. If
172 * the argument is already in the target domain, then
173 * the argument is returned, otherwise a copy.
175 [MethodImplAttribute(MethodImplOptions.InternalCall)]
176 private extern static byte[] ByteArrayToRootDomain (byte[] arr);
178 [MethodImplAttribute(MethodImplOptions.InternalCall)]
179 private extern static byte[] ByteArrayToCurrentDomain (byte[] arr);
181 static void DeserializePrincipal (Thread th)
183 MemoryStream ms = new MemoryStream (ByteArrayToCurrentDomain (th.Internal._serialized_principal));
184 int type = ms.ReadByte ();
186 BinaryFormatter bf = new BinaryFormatter ();
187 th.principal = (IPrincipal) bf.Deserialize (ms);
188 th.principal_version = th.Internal._serialized_principal_version;
189 } else if (type == 1) {
190 BinaryReader reader = new BinaryReader (ms);
191 string name = reader.ReadString ();
192 string auth_type = reader.ReadString ();
193 int n_roles = reader.ReadInt32 ();
194 string [] roles = null;
196 roles = new string [n_roles];
197 for (int i = 0; i < n_roles; i++)
198 roles [i] = reader.ReadString ();
200 th.principal = new GenericPrincipal (new GenericIdentity (name, auth_type), roles);
201 } else if (type == 2 || type == 3) {
202 string [] roles = type == 2 ? null : new string [0];
203 th.principal = new GenericPrincipal (new GenericIdentity ("", ""), roles);
207 static void SerializePrincipal (Thread th, IPrincipal value)
209 MemoryStream ms = new MemoryStream ();
211 if (value.GetType () == typeof (GenericPrincipal)) {
212 GenericPrincipal gp = (GenericPrincipal) value;
213 if (gp.Identity != null && gp.Identity.GetType () == typeof (GenericIdentity)) {
214 GenericIdentity id = (GenericIdentity) gp.Identity;
215 if (id.Name == "" && id.AuthenticationType == "") {
216 if (gp.Roles == null) {
219 } else if (gp.Roles.Length == 0) {
225 BinaryWriter br = new BinaryWriter (ms);
226 br.Write (gp.Identity.Name);
227 br.Write (gp.Identity.AuthenticationType);
228 string [] roles = gp.Roles;
230 br.Write ((int) (-1));
232 br.Write (roles.Length);
233 foreach (string s in roles) {
244 BinaryFormatter bf = new BinaryFormatter ();
246 bf.Serialize (ms, value);
249 th.Internal._serialized_principal = ByteArrayToRootDomain (ms.ToArray ());
252 public static IPrincipal CurrentPrincipal {
254 Thread th = CurrentThread;
256 if (th.principal_version != th.Internal._serialized_principal_version)
259 if (th.principal != null)
262 if (th.Internal._serialized_principal != null) {
264 DeserializePrincipal (th);
269 th.principal = GetDomain ().DefaultPrincipal;
270 th.principal_version = th.Internal._serialized_principal_version;
273 [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
275 Thread th = CurrentThread;
277 if (value != GetDomain ().DefaultPrincipal) {
278 ++th.Internal._serialized_principal_version;
280 SerializePrincipal (th, value);
281 } catch (Exception) {
282 th.Internal._serialized_principal = null;
284 th.principal_version = th.Internal._serialized_principal_version;
286 th.Internal._serialized_principal = null;
289 th.principal = value;
293 // Looks up the object associated with the current thread
294 // this is called by the JIT directly, too
295 [MethodImplAttribute(MethodImplOptions.InternalCall)]
296 private extern static InternalThread CurrentInternalThread_internal();
298 [MethodImplAttribute(MethodImplOptions.InternalCall)]
299 internal extern static uint AllocTlsData (Type type);
301 [MethodImplAttribute(MethodImplOptions.InternalCall)]
302 internal extern static void DestroyTlsData (uint offset);
304 public static Thread CurrentThread {
305 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
307 if (current_thread == null)
308 current_thread = new Thread (CurrentInternalThread_internal ());
309 return current_thread;
313 internal static int CurrentThreadId {
315 return (int)(CurrentThread.internal_thread.thread_id);
319 public static AppDomain GetDomain() {
320 return AppDomain.CurrentDomain;
323 [MethodImplAttribute(MethodImplOptions.InternalCall)]
324 public extern static int GetDomainID();
326 [MethodImplAttribute(MethodImplOptions.InternalCall)]
327 private extern static void ResetAbort_internal();
329 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
330 public static void ResetAbort ()
332 ResetAbort_internal ();
335 [HostProtectionAttribute (SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
336 [MethodImplAttribute(MethodImplOptions.InternalCall)]
337 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
338 public extern static bool Yield ();
341 [MethodImplAttribute(MethodImplOptions.InternalCall)]
342 private extern static void Sleep_internal(int ms);
344 public static void Sleep (int millisecondsTimeout)
346 if (millisecondsTimeout < Timeout.Infinite)
347 throw new ArgumentOutOfRangeException ("millisecondsTimeout", "Negative timeout");
349 Sleep_internal (millisecondsTimeout);
352 public static void Sleep (TimeSpan timeout)
354 long ms = (long) timeout.TotalMilliseconds;
355 if (ms < Timeout.Infinite || ms > Int32.MaxValue)
356 throw new ArgumentOutOfRangeException ("timeout", "timeout out of range");
358 Sleep_internal ((int) ms);
361 // Returns the system thread handle
362 [MethodImplAttribute(MethodImplOptions.InternalCall)]
363 private extern IntPtr Thread_internal (MulticastDelegate start);
365 public Thread(ThreadStart start) {
367 throw new ArgumentNullException("Null ThreadStart");
372 private Thread (InternalThread it) {
373 internal_thread = it;
376 // part of ".NETPortable,Version=v4.0,Profile=Profile3" i.e. FX4 and SL4
377 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
382 [Obsolete ("Deprecated in favor of GetApartmentState, SetApartmentState and TrySetApartmentState.")]
383 public ApartmentState ApartmentState {
385 if ((ThreadState & ThreadState.Stopped) != 0)
386 throw new ThreadStateException ("Thread is dead; state can not be accessed.");
388 return (ApartmentState)Internal.apartment_state;
392 TrySetApartmentState (value);
396 //[MethodImplAttribute (MethodImplOptions.InternalCall)]
397 //private static extern int current_lcid ();
399 public CultureInfo CurrentCulture {
401 CultureInfo culture = current_culture;
402 if (current_culture_set && culture != null)
405 if (default_culture != null)
406 return default_culture;
408 current_culture = culture = CultureInfo.ConstructCurrentCulture ();
412 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
415 throw new ArgumentNullException ("value");
417 value.CheckNeutral ();
418 current_culture = value;
419 current_culture_set = true;
423 public CultureInfo CurrentUICulture {
425 CultureInfo culture = current_ui_culture;
426 if (current_ui_culture_set && culture != null)
429 if (default_ui_culture != null)
430 return default_ui_culture;
432 current_ui_culture = culture = CultureInfo.ConstructCurrentUICulture ();
438 throw new ArgumentNullException ("value");
439 current_ui_culture = value;
440 current_ui_culture_set = true;
444 public bool IsThreadPoolThread {
446 return IsThreadPoolThreadInternal;
450 internal bool IsThreadPoolThreadInternal {
452 return Internal.threadpool_thread;
455 Internal.threadpool_thread = value;
459 public bool IsAlive {
461 ThreadState curstate = GetState (Internal);
463 if((curstate & ThreadState.Aborted) != 0 ||
464 (curstate & ThreadState.Stopped) != 0 ||
465 (curstate & ThreadState.Unstarted) != 0) {
473 public bool IsBackground {
475 ThreadState thread_state = GetState (Internal);
476 if ((thread_state & ThreadState.Stopped) != 0)
477 throw new ThreadStateException ("Thread is dead; state can not be accessed.");
479 return (thread_state & ThreadState.Background) != 0;
484 SetState (Internal, ThreadState.Background);
486 ClrState (Internal, ThreadState.Background);
491 [MethodImplAttribute(MethodImplOptions.InternalCall)]
492 private extern static string GetName_internal (InternalThread thread);
494 [MethodImplAttribute(MethodImplOptions.InternalCall)]
495 private extern static void SetName_internal (InternalThread thread, String name);
498 * The thread name must be shared by appdomains, so it is stored in
504 return GetName_internal (Internal);
508 SetName_internal (Internal, value);
512 public ThreadPriority Priority {
514 return (ThreadPriority)GetPriority (Internal);
518 // FIXME: This doesn't do anything yet
519 SetPriority (Internal, (int)value);
523 public ThreadState ThreadState {
525 return GetState (Internal);
529 [MethodImplAttribute(MethodImplOptions.InternalCall)]
530 private extern static void Abort_internal (InternalThread thread, object stateInfo);
532 [MethodImplAttribute(MethodImplOptions.InternalCall)]
533 private extern static int GetPriority (InternalThread thread);
535 [MethodImplAttribute(MethodImplOptions.InternalCall)]
536 private extern static void SetPriority (InternalThread thread, int priority);
538 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
541 Abort_internal (Internal, null);
544 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
545 public void Abort (object stateInfo)
547 Abort_internal (Internal, stateInfo);
550 [MethodImplAttribute(MethodImplOptions.InternalCall)]
551 extern object GetAbortExceptionState ();
553 internal object AbortReason {
555 return GetAbortExceptionState ();
559 [MethodImplAttribute (MethodImplOptions.InternalCall)]
560 private extern static void Interrupt_internal (InternalThread thread);
562 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
563 public void Interrupt ()
565 Interrupt_internal (Internal);
568 // The current thread joins with 'this'. Set ms to 0 to block
569 // until this actually exits.
570 [MethodImplAttribute(MethodImplOptions.InternalCall)]
571 private extern static bool Join_internal(InternalThread thread, int ms, IntPtr handle);
575 Join_internal(Internal, Timeout.Infinite, Internal.system_thread_handle);
578 public bool Join(int millisecondsTimeout)
580 if (millisecondsTimeout < Timeout.Infinite)
581 throw new ArgumentOutOfRangeException ("millisecondsTimeout", "Timeout less than zero");
583 return Join_internal (Internal, millisecondsTimeout, Internal.system_thread_handle);
586 public bool Join(TimeSpan timeout)
588 long ms = (long) timeout.TotalMilliseconds;
589 if (ms < Timeout.Infinite || ms > Int32.MaxValue)
590 throw new ArgumentOutOfRangeException ("timeout", "timeout out of range");
592 return Join_internal (Internal, (int) ms, Internal.system_thread_handle);
595 [MethodImplAttribute(MethodImplOptions.InternalCall)]
596 public extern static void MemoryBarrier ();
598 [MethodImplAttribute(MethodImplOptions.InternalCall)]
599 private extern void Resume_internal();
602 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
603 public void Resume ()
608 [MethodImplAttribute (MethodImplOptions.InternalCall)]
609 private extern static void SpinWait_nop ();
612 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
613 public static void SpinWait (int iterations)
617 while (iterations-- > 0)
623 private void StartInternal ()
625 current_thread = this;
627 if (m_Delegate is ThreadStart) {
628 ((ThreadStart) m_Delegate) ();
630 ((ParameterizedThreadStart) m_Delegate) (m_ThreadStartArg);
634 public void Start() {
635 // propagate informations from the original thread to the new thread
636 ec_to_set = ExecutionContext.Capture (false, true);
637 Internal._serialized_principal = CurrentThread.Internal._serialized_principal;
639 // Thread_internal creates and starts the new thread,
640 if (Thread_internal((ThreadStart) StartInternal) == (IntPtr) 0)
641 throw new SystemException ("Thread creation failed.");
644 [MethodImplAttribute(MethodImplOptions.InternalCall)]
645 private extern static void Suspend_internal(InternalThread thread);
648 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
649 public void Suspend ()
651 Suspend_internal (Internal);
654 [MethodImplAttribute (MethodImplOptions.InternalCall)]
655 extern private static void SetState (InternalThread thread, ThreadState set);
657 [MethodImplAttribute (MethodImplOptions.InternalCall)]
658 extern private static void ClrState (InternalThread thread, ThreadState clr);
660 [MethodImplAttribute (MethodImplOptions.InternalCall)]
661 extern private static ThreadState GetState (InternalThread thread);
663 [MethodImplAttribute (MethodImplOptions.InternalCall)]
664 extern public static byte VolatileRead (ref byte address);
666 [MethodImplAttribute (MethodImplOptions.InternalCall)]
667 extern public static double VolatileRead (ref double address);
669 [MethodImplAttribute (MethodImplOptions.InternalCall)]
670 extern public static short VolatileRead (ref short address);
672 [MethodImplAttribute (MethodImplOptions.InternalCall)]
673 extern public static int VolatileRead (ref int address);
675 [MethodImplAttribute (MethodImplOptions.InternalCall)]
676 extern public static long VolatileRead (ref long address);
678 [MethodImplAttribute (MethodImplOptions.InternalCall)]
679 extern public static IntPtr VolatileRead (ref IntPtr address);
681 [MethodImplAttribute (MethodImplOptions.InternalCall)]
682 extern public static object VolatileRead (ref object address);
684 [CLSCompliant(false)]
685 [MethodImplAttribute (MethodImplOptions.InternalCall)]
686 extern public static sbyte VolatileRead (ref sbyte address);
688 [MethodImplAttribute (MethodImplOptions.InternalCall)]
689 extern public static float VolatileRead (ref float address);
691 [CLSCompliant (false)]
692 [MethodImplAttribute (MethodImplOptions.InternalCall)]
693 extern public static ushort VolatileRead (ref ushort address);
695 [CLSCompliant (false)]
696 [MethodImplAttribute (MethodImplOptions.InternalCall)]
697 extern public static uint VolatileRead (ref uint address);
699 [CLSCompliant (false)]
700 [MethodImplAttribute (MethodImplOptions.InternalCall)]
701 extern public static ulong VolatileRead (ref ulong address);
703 [CLSCompliant (false)]
704 [MethodImplAttribute (MethodImplOptions.InternalCall)]
705 extern public static UIntPtr VolatileRead (ref UIntPtr address);
707 [MethodImplAttribute (MethodImplOptions.InternalCall)]
708 extern public static void VolatileWrite (ref byte address, byte value);
710 [MethodImplAttribute (MethodImplOptions.InternalCall)]
711 extern public static void VolatileWrite (ref double address, double value);
713 [MethodImplAttribute (MethodImplOptions.InternalCall)]
714 extern public static void VolatileWrite (ref short address, short value);
716 [MethodImplAttribute (MethodImplOptions.InternalCall)]
717 extern public static void VolatileWrite (ref int address, int value);
719 [MethodImplAttribute (MethodImplOptions.InternalCall)]
720 extern public static void VolatileWrite (ref long address, long value);
722 [MethodImplAttribute (MethodImplOptions.InternalCall)]
723 extern public static void VolatileWrite (ref IntPtr address, IntPtr value);
725 [MethodImplAttribute (MethodImplOptions.InternalCall)]
726 extern public static void VolatileWrite (ref object address, object value);
728 [CLSCompliant(false)]
729 [MethodImplAttribute (MethodImplOptions.InternalCall)]
730 extern public static void VolatileWrite (ref sbyte address, sbyte value);
732 [MethodImplAttribute (MethodImplOptions.InternalCall)]
733 extern public static void VolatileWrite (ref float address, float value);
735 [CLSCompliant (false)]
736 [MethodImplAttribute (MethodImplOptions.InternalCall)]
737 extern public static void VolatileWrite (ref ushort address, ushort value);
739 [CLSCompliant (false)]
740 [MethodImplAttribute (MethodImplOptions.InternalCall)]
741 extern public static void VolatileWrite (ref uint address, uint value);
743 [CLSCompliant (false)]
744 [MethodImplAttribute (MethodImplOptions.InternalCall)]
745 extern public static void VolatileWrite (ref ulong address, ulong value);
747 [CLSCompliant (false)]
748 [MethodImplAttribute (MethodImplOptions.InternalCall)]
749 extern public static void VolatileWrite (ref UIntPtr address, UIntPtr value);
751 [MethodImplAttribute (MethodImplOptions.InternalCall)]
752 extern static int SystemMaxStackStize ();
754 static int GetProcessDefaultStackSize (int maxStackSize)
756 if (maxStackSize < 131072) // make sure stack is at least 128k big
759 int page_size = Environment.GetPageSize ();
761 if ((maxStackSize % page_size) != 0) // round up to a divisible of page size
762 maxStackSize = (maxStackSize / (page_size - 1)) * page_size;
764 /* Respect the max stack size imposed by the system*/
765 return Math.Min (maxStackSize, SystemMaxStackStize ());
768 void SetStart (MulticastDelegate start, int maxStackSize)
771 Internal.stack_size = maxStackSize;
774 public ExecutionContext ExecutionContext {
775 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
778 _ec = new ExecutionContext ();
786 internal bool HasExecutionContext {
792 internal void BranchExecutionContext (out ExecutionContext.Switcher switcher)
795 switcher = new ExecutionContext.Switcher ();
797 switcher = new ExecutionContext.Switcher (_ec);
798 _ec.CopyOnWrite = true;
802 internal void RestoreExecutionContext (ref ExecutionContext.Switcher switcher)
804 if (switcher.IsEmpty) {
809 switcher.Restore (_ec);
812 public int ManagedThreadId {
813 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
815 return Internal.managed_id;
819 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
820 public static void BeginCriticalRegion ()
822 CurrentThread.Internal.critical_region_level++;
825 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
826 public static void EndCriticalRegion ()
828 CurrentThread.Internal.critical_region_level--;
831 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
832 public static void BeginThreadAffinity ()
834 // Managed and native threads are currently bound together.
837 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
838 public static void EndThreadAffinity ()
840 // Managed and native threads are currently bound together.
843 public ApartmentState GetApartmentState ()
845 return (ApartmentState)Internal.apartment_state;
848 public void SetApartmentState (ApartmentState state)
850 if (!TrySetApartmentState (state))
851 throw new InvalidOperationException ("Failed to set the specified COM apartment state.");
854 public bool TrySetApartmentState (ApartmentState state)
856 if ((ThreadState & ThreadState.Unstarted) == 0)
857 throw new ThreadStateException ("Thread was in an invalid state for the operation being executed.");
859 if ((ApartmentState)Internal.apartment_state != ApartmentState.Unknown &&
860 (ApartmentState)Internal.apartment_state != state)
863 Internal.apartment_state = (byte)state;
869 public override int GetHashCode ()
871 return ManagedThreadId;
874 public void Start (object parameter)
876 m_ThreadStartArg = parameter;
880 internal CultureInfo GetCurrentUICultureNoAppX ()
882 return CultureInfo.CurrentUICulture;