diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs index 113dee97d0c660..96048ecdf4837b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs @@ -94,7 +94,6 @@ private void InitializeCulture() } } -#if !MONO // Workaround for #46389 public Thread(ThreadStart start) { if (start == null) @@ -237,7 +236,6 @@ private void SetCultureOnUnstartedThread(CultureInfo value, bool uiCulture) startHelper._culture = value; } } -#endif // Workaround for #46389 partial void ThreadNameChanged(string? value); diff --git a/src/mono/mono/metadata/threads.c b/src/mono/mono/metadata/threads.c index 755cfb0f07f52b..7d3875bdf4f3bb 100644 --- a/src/mono/mono/metadata/threads.c +++ b/src/mono/mono/metadata/threads.c @@ -1940,8 +1940,11 @@ ves_icall_System_Threading_InternalThread_Thread_free_internal (MonoInternalThre mono_threads_close_native_thread_handle (MONO_GPOINTER_TO_NATIVE_THREAD_HANDLE (this_obj->native_handle)); this_obj->native_handle = NULL; - /* Possibly free synch_cs, if the thread already detached also. */ - dec_longlived_thread_data (this_obj->longlived); + /* might be null if the constructor threw an exception */ + if (this_obj->longlived) { + /* Possibly free synch_cs, if the thread already detached also. */ + dec_longlived_thread_data (this_obj->longlived); + } mono_thread_name_cleanup (&this_obj->name); } diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Threading/Thread.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Threading/Thread.Mono.cs index 104995fc59f147..d9f317ae75e62f 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Threading/Thread.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Threading/Thread.Mono.cs @@ -71,9 +71,7 @@ public partial class Thread #pragma warning restore 169, 414, 649 private string? _name; - private Delegate? m_start; - private object? m_start_arg; - private CultureInfo? culture, ui_culture; + private StartHelper? _startHelper; internal ExecutionContext? _executionContext; internal SynchronizationContext? _synchronizationContext; @@ -175,90 +173,6 @@ public ThreadPriority Priority public ThreadState ThreadState => GetState(this); - public Thread(ThreadStart start) - : this() - { - if (start == null) - { - throw new ArgumentNullException(nameof(start)); - } - - Create(start); - } - - public Thread(ThreadStart start, int maxStackSize) - : this() - { - if (start == null) - { - throw new ArgumentNullException(nameof(start)); - } - if (maxStackSize < 0) - { - throw new ArgumentOutOfRangeException(nameof(maxStackSize), SR.ArgumentOutOfRange_NeedNonNegNum); - } - - Create(start, maxStackSize); - } - - public Thread(ParameterizedThreadStart start) - : this() - { - if (start == null) - { - throw new ArgumentNullException(nameof(start)); - } - - Create(start); - } - - public Thread(ParameterizedThreadStart start, int maxStackSize) - : this() - { - if (start == null) - { - throw new ArgumentNullException(nameof(start)); - } - if (maxStackSize < 0) - { - throw new ArgumentOutOfRangeException(nameof(maxStackSize), SR.ArgumentOutOfRange_NeedNonNegNum); - } - - Create(start, maxStackSize); - } - - private void RequireCurrentThread() - { - if (this != CurrentThread) - { - throw new InvalidOperationException(SR.Thread_Operation_RequiresCurrentThread); - } - } - - private void SetCultureOnUnstartedThread(CultureInfo value, bool uiCulture) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - if ((ThreadState & ThreadState.Unstarted) == 0) - { - throw new InvalidOperationException(SR.Thread_Operation_RequiresCurrentThread); - } - if (uiCulture) - ui_culture = value; - else - culture = value; - } - - private void Create(ThreadStart start) => SetStartHelper((Delegate)start, 0); // 0 will setup Thread with default stackSize - - private void Create(ThreadStart start, int maxStackSize) => SetStartHelper((Delegate)start, maxStackSize); - - private void Create(ParameterizedThreadStart start) => SetStartHelper((Delegate)start, 0); - - private void Create(ParameterizedThreadStart start, int maxStackSize) => SetStartHelper((Delegate)start, maxStackSize); - public ApartmentState GetApartmentState() => ApartmentState.Unknown; public void DisableComObjectEagerCleanup() @@ -291,10 +205,12 @@ public bool Join(int millisecondsTimeout) return JoinInternal(this, millisecondsTimeout); } - private void SetStartHelper(Delegate start, int maxStackSize) + private void Initialize() { - m_start = start; - stack_size = maxStackSize; + InitInternal(this); + + // TODO: This can go away once the mono/mono mirror is disabled + stack_size = _startHelper!._maxStackSize; } public static void SpinWait(int iterations) @@ -316,103 +232,28 @@ public static void Sleep(int millisecondsTimeout) internal static void UninterruptibleSleep0() => SleepInternal(0, false); -#if !TARGET_BROWSER - internal const bool IsThreadStartSupported = true; - - [UnsupportedOSPlatform("browser")] - public void Start() - { - _executionContext = ExecutionContext.Capture(); - StartInternal(this); - } - - [UnsupportedOSPlatform("browser")] - public void Start(object parameter) - { - if (m_start is ThreadStart) - throw new InvalidOperationException(SR.InvalidOperation_ThreadWrongThreadStart); - - m_start_arg = parameter; - Start(); - } - - [UnsupportedOSPlatform("browser")] - internal void UnsafeStart() - { - StartInternal(this); - } - - [UnsupportedOSPlatform("browser")] - internal void UnsafeStart(object parameter) - { - Debug.Assert(m_start is ThreadStart); - - m_start_arg = parameter; - UnsafeStart(); - } - // Called from the runtime internal void StartCallback() { - ExecutionContext? context = _executionContext; - _executionContext = null; - if (context != null && !context.IsDefault) - { - ExecutionContext.RunInternal(context, s_threadStartContextCallback, this); - } - else - { - StartCallbackWorker(); - } - } - - private static readonly ContextCallback s_threadStartContextCallback = new ContextCallback(StartCallback_Context); - - private static void StartCallback_Context(object? state) - { - Debug.Assert(state is Thread); - ((Thread)state).StartCallbackWorker(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] // otherwise an unnecessary long-lived stack frame in many threads - private void StartCallbackWorker() - { - if (culture != null) - { - CultureInfo.CurrentCulture = culture; - culture = null; - } + StartHelper? startHelper = _startHelper; + Debug.Assert(startHelper != null); + _startHelper = null; - if (ui_culture != null) - { - CultureInfo.CurrentUICulture = ui_culture; - ui_culture = null; - } - - if (m_start is ThreadStart del) - { - m_start = null; - del(); - } - else - { - Debug.Assert(m_start is ParameterizedThreadStart); - var pdel = (ParameterizedThreadStart)m_start!; - object? arg = m_start_arg; - m_start = null; - m_start_arg = null; - pdel(arg); - } + startHelper.Run(); } // Called from the runtime internal static void ThrowThreadStartException(Exception ex) => throw new ThreadStartException(ex); + private void StartCore() + { + StartInternal(this); + } + [DynamicDependency(nameof(StartCallback))] [DynamicDependency(nameof(ThrowThreadStartException))] [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void StartInternal(Thread runtime_thread); -#endif partial void ThreadNameChanged(string? value) {