Skip to content

[src] Clean/consolidate runtime initialization code between platforms.#26131

Draft
rolfbjarne wants to merge 4 commits into
mainfrom
dev/rolf/synchronize-initialize
Draft

[src] Clean/consolidate runtime initialization code between platforms.#26131
rolfbjarne wants to merge 4 commits into
mainfrom
dev/rolf/synchronize-initialize

Conversation

@rolfbjarne

Copy link
Copy Markdown
Member
  • Add Runtime.EnsureUIThread (), and call this method from [NS|UI]Application.EnsureUIThread. Also move supporting code to the Runtime class.
  • Remove NSApplication.EnsureInitialized - this was necessary to ensure xamarin_initialize was called when Xamarin.Mac was hosted inside another application (such as Visual Studio for Mac). .NET for macOS no longer supports being hosted inside another application, so this code can be removed.
  • Remove Runtime.RegisterAssemblies () - it's no longer needed because .NET for macOS doesn't support being hosted inside another app.
  • Don't set MONO_CFG_DIR anymore - this is old code, and shouldn't be needed now. If anybody does, then they can set this variable themselves.
  • Remove NSApplication.ResetHandle () - it's no longer needed because .NET for macOS doesn't support being hosted inside another app.
  • Add NSApplication.Initialize () - this mirrors UIApplication.Initialize ()
  • Remove NSApplication.InitDrawBridge () - this is not applicable for .NET for macOS (not fully removed until XAMCORE_5_0)
  • Remove NSApplication.Init () - this is not needed anymore in .NET for macOS (not fully removed until XAMCORE_5_0)
  • Make the various [NS|UI]Application.Main methods return 'int' in XAMCORE_5_0.
  • Misc other dead code fixes.
  • Misc xml documentation updates.

rolfbjarne and others added 2 commits July 16, 2026 15:23
* Add Runtime.EnsureUIThread (), and call this method from [NS|UI]Application.EnsureUIThread. Also move supporting code to the Runtime class.
* Remove NSApplication.EnsureInitialized - this was necessary to ensure `xamarin_initialize` was called when Xamarin.Mac was hosted inside another application (such as Visual Studio for Mac). .NET for macOS no longer supports being hosted inside another application, so this code can be removed.
* Remove Runtime.RegisterAssemblies () - it's no longer needed because .NET for macOS doesn't support being hosted inside another app.
* Don't set MONO_CFG_DIR anymore - this is *old* code, and shouldn't be needed now. If anybody does, then they can set this variable themselves.
* Remove NSApplication.ResetHandle () - it's no longer needed because .NET for macOS doesn't support being hosted inside another app.
* Add NSApplication.Initialize () - this mirrors UIApplication.Initialize ()
* Remove NSApplication.InitDrawBridge () - this is not applicable for .NET for macOS (not fully removed until XAMCORE_5_0)
* Remove NSApplication.Init () - this is not needed anymore in .NET for macOS (not fully removed until XAMCORE_5_0)
* Make the various [NS|UI]Application.Main methods return 'int' in XAMCORE_5_0.
* Misc other dead code fixes.
* Misc xml documentation updates.
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

rolfbjarne and others added 2 commits July 16, 2026 20:14
The consolidated Runtime.EnsureUIThread returned early when
CheckForIllegalCrossThreadCalls was true, which is exactly when the check
should run. This meant the UIKit/AppKit cross-thread access exceptions were
never thrown, breaking the monotouch-test DispatchTests on iOS/tvOS/Mac
Catalyst (they got a NullReferenceException instead of a
UIKitThreadAccessException).

Invert the condition so the check runs when CheckForIllegalCrossThreadCalls
is enabled.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The consolidation moved the AppKitSynchronizationContext setup out of
NSApplication.Init and into Runtime.InitializePlatform, which runs during
early native startup (xamarin_initialize).

Hosts and the test runner (MacRunner) start the main run loop by calling
NSApplication.Init followed by NSApplication.SharedApplication.Run,
*without* going through NSApplication.Main. On base, NSApplication.Init
established the synchronization context on that run-loop thread; after the
consolidation it no longer did, so the context was no longer guaranteed to
be current on the thread that actually runs the app.

This is the same pattern iOS already uses (UIApplication.Main calls
UIApplication.Initialize on the run-loop thread), and it fixes the
link-all macOS PrintPreview_NSGraphicsContextCurrentContext hang, where the
modal print operation could no longer be aborted via a continuation posted
to the (missing) AppKit synchronization context.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ API diff for current PR / commit

NET (empty diffs)

✅ API diff vs stable

NET (empty diffs)

ℹ️ Generator diff

Generator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes)

Pipeline on Agent
Hash: ce719bdb30c76ea19e5f2ebc73b54dc266e7038b [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

🔥 [CI Build #ce719bd] Test results 🔥

Test results

❌ Tests failed on VSTS: test results

3 tests crashed, 4 tests failed, 178 tests passed.

Failures

❌ cecil tests

1 tests failed, 0 tests passed.

Failed tests

  • Cecil-based tests: Failed (Execution failed with exit code 1)
    • Cecil.Tests.ApiTest.BannedAttributes: Known failures that aren't failing anymore - remove these from the list of known failures: APIs with [Preserve] - alternative ...

Html Report (VSDrops) Download

❌ dotnettests tests (iOS)

🔥 Failed catastrophically on VSTS: test results - dotnettests_ios (no summary found).

Html Report (VSDrops) Download

❌ dotnettests tests (MacCatalyst)

1 tests failed, 0 tests passed.

Failed tests

  • DotNet tests: Failed (Execution failed with exit code 1)
    • Xamarin.Tests.AppSizeTest.MonoVM_Interpreter(MacCatalyst,"maccat...: Multiple failures or warnings in test:
  1. Unexpected APIs were added to the preserved set. The updated expected file is avai...
    * Xamarin.Tests.AppSizeTest.MonoVM(MacCatalyst,"maccatalyst-arm64"...: Multiple failures or warnings in test:
  2. Unexpected APIs were added to the preserved set. The updated expected file is avai...

Html Report (VSDrops) Download

❌ dotnettests tests (macOS)

1 tests failed, 0 tests passed.

Failed tests

  • DotNet tests: Failed (Execution failed with exit code 1)
    • Xamarin.Tests.AppSizeTest.NativeAOT(MacOSX,"osx-arm64;osx-x64"): App size changed significantly (-16,774 bytes (-16.4 KB = -0.0 MB) different > tolerance of +-10,240 bytes (10.0 KB = 0.0 MB)). ...

Html Report (VSDrops) Download

❌ dotnettests tests (tvOS)

1 tests failed, 0 tests passed.

Failed tests

  • DotNet tests: Failed (Execution failed with exit code 1)
    • Xamarin.Tests.AppSizeTest.MonoVM_Interpreter(TVOS,"tvos-arm64"): Multiple failures or warnings in test:
  1. Unexpected APIs were added to the preserved set. The updated expected file is avai...
    * Xamarin.Tests.AppSizeTest.MonoVM(TVOS,"tvos-arm64"): Multiple failures or warnings in test:
  2. Unexpected APIs were added to the preserved set. The updated expected file is avai...

Html Report (VSDrops) Download

❌ monotouch tests (macOS)

🔥 Failed catastrophically on VSTS: test results - monotouch_macos (no summary found).

Html Report (VSDrops) Download

❌ xtro tests

🔥 Failed catastrophically on VSTS: test results - xtro (no summary found).

Html Report (VSDrops) Download

Successes

✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (Multiple platforms): All 1 tests passed. Html Report (VSDrops) Download
✅ framework: All 2 tests passed. Html Report (VSDrops) Download
✅ fsharp: All 4 tests passed. Html Report (VSDrops) Download
✅ generator: All 5 tests passed. Html Report (VSDrops) Download
✅ interdependent-binding-projects: All 4 tests passed. Html Report (VSDrops) Download
✅ introspection: All 4 tests passed. Html Report (VSDrops) Download
✅ linker (iOS): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (MacCatalyst): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (macOS): All 21 tests passed. Html Report (VSDrops) Download
✅ linker (tvOS): All 15 tests passed. Html Report (VSDrops) Download
✅ monotouch (iOS): All 19 tests passed. Html Report (VSDrops) Download
✅ monotouch (MacCatalyst): All 18 tests passed. Html Report (VSDrops) Download
✅ monotouch (tvOS): All 19 tests passed. Html Report (VSDrops) Download
✅ msbuild: All 2 tests passed. Html Report (VSDrops) Download
✅ sharpie: All 1 tests passed. Html Report (VSDrops) Download
✅ windows: All 3 tests passed. Html Report (VSDrops) Download
✅ xcframework: All 4 tests passed. Html Report (VSDrops) Download

macOS tests

✅ Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Ventura (13): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sonoma (14): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sequoia (15): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Tahoe (26): All 5 tests passed. Html Report (VSDrops) Download

Linux Build Verification

Linux build succeeded

Pipeline on Agent
Hash: ce719bdb30c76ea19e5f2ebc73b54dc266e7038b [PR build]

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR consolidates cross-platform runtime/UI-thread initialization by moving UI-thread enforcement logic into ObjCRuntime.Runtime, and by simplifying AppKit/UIKit initialization paths now that .NET for macOS is no longer hostable inside other applications.

Changes:

  • Centralized UI-thread enforcement in ObjCRuntime.Runtime.EnsureUIThread (), and routed UIApplication.EnsureUIThread / NSApplication.EnsureUIThread through it.
  • Introduced NSApplication.Initialize () (to mirror UIApplication.Initialize ()) and adjusted macOS runtime platform initialization to call it.
  • Updated UIApplication.Main / NSApplication.Main to return int under XAMCORE_5_0 and performed associated cleanup of older initialization code paths.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/UIKit/UIApplication.cs Routes EnsureUIThread to Runtime.EnsureUIThread and updates Main overloads to return int in XAMCORE_5_0.
src/ObjCRuntime/Runtime.mac.cs Calls NSApplication.Initialize () during platform initialization.
src/ObjCRuntime/Runtime.iOS.cs Adds Mac Catalyst product/assembly naming constants and keeps UIApplication.Initialize () as the platform initializer.
src/ObjCRuntime/Runtime.cs Stores main thread during runtime init and introduces centralized EnsureUIThread ().
src/AppKit/NSApplication.cs Adds Initialize (), simplifies Init/Main, and routes EnsureUIThread to Runtime.EnsureUIThread.

Comment on lines +60 to 63
static void Initialize ()
{
// `class_ptr` is `readonly` so one can't simply do `class_ptr = Class.GetHandle ("NSApplication");`
typeof (NSApplication).GetField ("class_ptr", BindingFlags.Static | BindingFlags.NonPublic)?.SetValue (null, Class.GetHandle ("NSApplication"));
SynchronizationContext.SetSynchronizationContext (new AppKitSynchronizationContext ());
}
Comment on lines 28 to 33
#if TVOS
internal const string AssemblyName = "Microsoft.tvOS.dll";
#elif __MACCATALYST__
internal const string AssemblyName = "Microsoft.MacCatalyst";
#elif IOS
internal const string AssemblyName = "Microsoft.iOS.dll";
Comment on lines +389 to +403
/// <summary>Assertion to ensure that this call is being done from the UIKit thread.</summary>
/// <remarks>
/// <para>
/// This method is used internally by MonoTouch to ensure that
/// accesses done to UIKit classes and methods are only
/// performed from the UIKit thread. This is necessary because
/// the UIKit API is not thread-safe and accessing it from
/// multiple threads will corrupt the application state and will
/// likely lead to a crash that is hard to identify.
/// </para>
/// <para>
/// MonoTouch only performs the thread checks in debug builds.
/// Release builds have this feature disabled.
/// </para>
/// </remarks>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants