Bladeren bron

Modernize project structure: move to Core/ and Platforms/, remove obsolete files, update solution and VSCode configs

CartBlanche 2 weken geleden
bovenliggende
commit
6accb61daf
32 gewijzigde bestanden met toevoegingen van 912 en 607 verwijderingen
  1. 7 0
      BackgroundThreadTester/.vscode/extensions.json
  2. 67 0
      BackgroundThreadTester/.vscode/launch.json
  3. 16 0
      BackgroundThreadTester/.vscode/settings.json
  4. 136 0
      BackgroundThreadTester/.vscode/tasks.json
  5. 0 91
      BackgroundThreadTester/BackgroundThreadTester.MacOS.csproj
  6. 42 0
      BackgroundThreadTester/BackgroundThreadTester.sln
  7. 13 0
      BackgroundThreadTester/Core/BackgroundThreadTester.Core.csproj
  8. 0 0
      BackgroundThreadTester/Core/Content/UiCursor.xnb
  9. 0 0
      BackgroundThreadTester/Core/Content/beehive.png
  10. 0 0
      BackgroundThreadTester/Core/Content/beehive.xnb
  11. 0 0
      BackgroundThreadTester/Core/Content/fntStandard.xnb
  12. 16 16
      BackgroundThreadTester/Core/Enums.cs
  13. 230 0
      BackgroundThreadTester/Core/Game1.cs
  14. 0 8
      BackgroundThreadTester/Core/InputManager.cs
  15. 72 80
      BackgroundThreadTester/Core/Object.cs
  16. 0 0
      BackgroundThreadTester/Core/TestTexture.cs
  17. 0 9
      BackgroundThreadTester/Core/TextManager.cs
  18. 0 195
      BackgroundThreadTester/Game1.cs
  19. 0 18
      BackgroundThreadTester/Info.plist
  20. 0 118
      BackgroundThreadTester/MainMenu.xib
  21. 12 0
      BackgroundThreadTester/Platforms/Android/AndroidManifest.xml
  22. 16 0
      BackgroundThreadTester/Platforms/Android/BackgroundThreadTester.Android.csproj
  23. 20 0
      BackgroundThreadTester/Platforms/Android/Program.cs
  24. 17 0
      BackgroundThreadTester/Platforms/DesktopGL/BackgroundThreadTester.DesktopGL.csproj
  25. 14 0
      BackgroundThreadTester/Platforms/DesktopGL/Program.cs
  26. 18 0
      BackgroundThreadTester/Platforms/Windows/BackgroundThreadTester.Windows.csproj
  27. 17 0
      BackgroundThreadTester/Platforms/Windows/Program.cs
  28. 16 0
      BackgroundThreadTester/Platforms/iOS/BackgroundThreadTester.iOS.csproj
  29. 22 0
      BackgroundThreadTester/Platforms/iOS/Info.plist
  30. 30 0
      BackgroundThreadTester/Platforms/iOS/Program.cs
  31. 0 67
      BackgroundThreadTester/Program.cs
  32. 131 5
      BackgroundThreadTester/README.md

+ 7 - 0
BackgroundThreadTester/.vscode/extensions.json

@@ -0,0 +1,7 @@
+{
+    "recommendations": [
+        "ms-dotnettools.csharp",
+        "ms-dotnettools.vscode-dotnet-runtime",
+        "ms-vscode.mono-debug"
+    ]
+}

+ 67 - 0
BackgroundThreadTester/.vscode/launch.json

@@ -0,0 +1,67 @@
+{
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "name": "Launch Windows",
+            "type": "coreclr",
+            "request": "launch",
+            "preLaunchTask": "build-windows",
+            "program": "${workspaceFolder}/bin/Debug/net8.0-windows/BackgroundThreadTester.Windows.exe",
+            "args": [],
+            "cwd": "${workspaceFolder}",
+            "console": "internalConsole",
+            "stopAtEntry": false,
+            "requireExactSource": false,
+            "justMyCode": false,
+            "env": {
+                "DOTNET_ENVIRONMENT": "Development"
+            }
+        },
+        {
+            "name": "Launch DesktopGL",
+            "type": "coreclr",
+            "request": "launch",
+            "preLaunchTask": "build-desktopgl", 
+            "program": "${workspaceFolder}/bin/Debug/net8.0/BackgroundThreadTester.DesktopGL.exe",
+            "args": [],
+            "cwd": "${workspaceFolder}",
+            "console": "internalConsole",
+            "stopAtEntry": false,
+            "requireExactSource": false,
+            "justMyCode": false,
+            "env": {
+                "DOTNET_ENVIRONMENT": "Development"
+            }
+        },
+        {
+            "name": "Attach to Process",
+            "type": "coreclr",
+            "request": "attach",
+            "processId": "${command:pickProcess}"
+        },
+        {
+            "name": "Launch Windows (External Console)",
+            "type": "coreclr",
+            "request": "launch",
+            "preLaunchTask": "build-windows",
+            "program": "${workspaceFolder}/bin/Debug/net8.0-windows/BackgroundThreadTester.Windows.exe",
+            "args": [],
+            "cwd": "${workspaceFolder}",
+            "console": "externalTerminal",
+            "stopAtEntry": false,
+            "requireExactSource": false
+        },
+        {
+            "name": "Launch DesktopGL (External Console)",
+            "type": "coreclr",
+            "request": "launch",
+            "preLaunchTask": "build-desktopgl",
+            "program": "${workspaceFolder}/bin/Debug/net8.0/BackgroundThreadTester.DesktopGL.exe",
+            "args": [],
+            "cwd": "${workspaceFolder}",
+            "console": "externalTerminal",
+            "stopAtEntry": false,
+            "requireExactSource": false
+        }
+    ]
+}

+ 16 - 0
BackgroundThreadTester/.vscode/settings.json

@@ -0,0 +1,16 @@
+{
+    "dotnet.defaultSolution": "BackgroundThreadTester.Modern.sln",
+    "omnisharp.enableEditorConfigSupport": true,
+    "omnisharp.enableRoslynAnalyzers": true,
+    "files.exclude": {
+        "**/bin": true,
+        "**/obj": true,
+        "**/.vs": true
+    },
+    "search.exclude": {
+        "**/bin": true,
+        "**/obj": true,
+        "**/.vs": true
+    },
+    "dotnet.completion.showCompletionItemsFromUnimportedNamespaces": true
+}

+ 136 - 0
BackgroundThreadTester/.vscode/tasks.json

@@ -0,0 +1,136 @@
+{
+    "version": "2.0.0",
+    "tasks": [
+        {
+            "label": "build-windows",
+            "type": "shell",
+            "command": "dotnet",
+            "args": ["build", "Platforms/Windows/BackgroundThreadTester.Windows.csproj"],
+            "group": "build",
+            "problemMatcher": "$msCompile",
+            "presentation": {
+                "echo": true,
+                "reveal": "silent",
+                "focus": false,
+                "panel": "shared"
+            }
+        },
+        {
+            "label": "build-desktopgl",
+            "type": "shell",
+            "command": "dotnet",
+            "args": ["build", "Platforms/DesktopGL/BackgroundThreadTester.DesktopGL.csproj"],
+            "group": "build",
+            "problemMatcher": "$msCompile",
+            "presentation": {
+                "echo": true,
+                "reveal": "silent",
+                "focus": false,
+                "panel": "shared"
+            }
+        },
+        {
+            "label": "build-android",
+            "type": "shell",
+            "command": "dotnet",
+            "args": ["build", "Platforms/Android/BackgroundThreadTester.Android.csproj"],
+            "group": "build",
+            "problemMatcher": "$msCompile",
+            "presentation": {
+                "echo": true,
+                "reveal": "silent",
+                "focus": false,
+                "panel": "shared"
+            }
+        },
+        {
+            "label": "build-ios",
+            "type": "shell",
+            "command": "dotnet",
+            "args": ["build", "Platforms/iOS/BackgroundThreadTester.iOS.csproj"],
+            "group": "build",
+            "problemMatcher": "$msCompile",
+            "presentation": {
+                "echo": true,
+                "reveal": "silent",
+                "focus": false,
+                "panel": "shared"
+            }
+        },
+        {
+            "label": "build-core",
+            "type": "shell",
+            "command": "dotnet",
+            "args": ["build", "Core/BackgroundThreadTester.Core.csproj"],
+            "group": "build",
+            "problemMatcher": "$msCompile",
+            "presentation": {
+                "echo": true,
+                "reveal": "silent",
+                "focus": false,
+                "panel": "shared"
+            }
+        },
+        {
+            "label": "run-windows",
+            "type": "shell",
+            "command": "dotnet",
+            "args": ["run", "--project", "Platforms/Windows/BackgroundThreadTester.Windows.csproj"],
+            "group": "build",
+            "problemMatcher": "$msCompile",
+            "presentation": {
+                "echo": true,
+                "reveal": "always",
+                "focus": false,
+                "panel": "shared"
+            },
+            "dependsOn": "build-windows"
+        },
+        {
+            "label": "run-desktopgl",
+            "type": "shell",
+            "command": "dotnet",
+            "args": ["run", "--project", "Platforms/DesktopGL/BackgroundThreadTester.DesktopGL.csproj"],
+            "group": "build",
+            "problemMatcher": "$msCompile",
+            "presentation": {
+                "echo": true,
+                "reveal": "always",
+                "focus": false,
+                "panel": "shared"
+            },
+            "dependsOn": "build-desktopgl"
+        },
+        {
+            "label": "run-desktopgl",
+            "type": "shell",
+            "command": "dotnet",
+            "args": ["run", "--project", "Platforms/DesktopGL/BackgroundThreadTester.DesktopGL.csproj"],
+            "group": "build",
+            "problemMatcher": "$msCompile",
+            "presentation": {
+                "echo": true,
+                "reveal": "always",
+                "focus": false,
+                "panel": "shared"
+            },
+            "dependsOn": "build-desktopgl"
+        },
+        {
+            "label": "clean",
+            "type": "shell",
+            "command": "dotnet",
+            "args": ["clean"],
+            "group": "build",
+            "problemMatcher": "$msCompile"
+        },
+        {
+            "label": "restore",
+            "type": "shell",
+            "command": "dotnet",
+            "args": ["restore"],
+            "group": "build",
+            "problemMatcher": "$msCompile"
+        }
+    ]
+}

+ 0 - 91
BackgroundThreadTester/BackgroundThreadTester.MacOS.csproj

@@ -1,91 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
-    <ProductVersion>10.0.0</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{8592FA21-37B6-41C8-BC7F-17EB4930B96A}</ProjectGuid>
-    <ProjectTypeGuids>{948B3504-5B70-4649-8FE4-BDE1FB46EC69};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
-    <OutputType>Exe</OutputType>
-    <RootNamespace>BackgroundThreadTester</RootNamespace>
-    <AssemblyName>BackgroundThreadTester</AssemblyName>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
-    <DebugSymbols>True</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>False</Optimize>
-    <OutputPath>bin\Debug</OutputPath>
-    <DefineConstants>DEBUG;</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <PlatformTarget>x86</PlatformTarget>
-    <ConsolePause>False</ConsolePause>
-    <EnableCodeSigning>False</EnableCodeSigning>
-    <CreatePackage>False</CreatePackage>
-    <EnablePackageSigning>False</EnablePackageSigning>
-    <IncludeMonoRuntime>False</IncludeMonoRuntime>
-    <UseSGen>False</UseSGen>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
-    <DebugType>none</DebugType>
-    <Optimize>False</Optimize>
-    <OutputPath>bin\Release</OutputPath>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <PlatformTarget>x86</PlatformTarget>
-    <ConsolePause>False</ConsolePause>
-    <EnableCodeSigning>False</EnableCodeSigning>
-    <CreatePackage>False</CreatePackage>
-    <EnablePackageSigning>False</EnablePackageSigning>
-    <IncludeMonoRuntime>False</IncludeMonoRuntime>
-    <UseSGen>False</UseSGen>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="System" />
-    <Reference Include="System.Xml" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Xml.Linq" />
-    <Reference Include="System.Drawing" />
-    <Reference Include="MonoMac" />
-    <Reference Include="System.Windows.Forms" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="Info.plist">
-    </None>
-    <None Include="Content\beehive.png" />
-    <None Include="README.md" />
-  </ItemGroup>
-  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
-  <Import Project="$(MSBuildExtensionsPath)\Mono\MonoMac\v0.0\Mono.MonoMac.targets" />
-  <ItemGroup>
-    <Folder Include="Content\" />
-  </ItemGroup>
-  <ItemGroup>
-    <Content Include="Content\fntStandard.xnb" />
-    <Content Include="Content\UiCursor.xnb" />
-    <Content Include="Content\beehive.xnb" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="Enums.cs" />
-    <Compile Include="Game1.cs" />
-    <Compile Include="InputManager.cs" />
-    <Compile Include="Object.cs" />
-    <Compile Include="Program.cs" />
-    <Compile Include="TextManager.cs" />
-    <Compile Include="TestTexture.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <InterfaceDefinition Include="MainMenu.xib" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="..\..\ThirdParty\Lidgren.Network\Lidgren.Network.MacOS.csproj">
-      <Project>{AE483C29-042E-4226-BA52-D247CE7676DA}</Project>
-      <Name>Lidgren.Network.MacOS</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\MonoGame.Framework\MonoGame.Framework.MacOS.csproj">
-      <Project>{36C538E6-C32A-4A8D-A39C-566173D7118E}</Project>
-      <Name>MonoGame.Framework.MacOS</Name>
-    </ProjectReference>
-  </ItemGroup>
-</Project>

+ 42 - 0
BackgroundThreadTester/BackgroundThreadTester.sln

@@ -0,0 +1,42 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.2.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BackgroundThreadTester.Windows", "BackgroundThreadTester.Windows.csproj", "{8592FA21-37B6-41C8-BC7F-17EB4930B96A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BackgroundThreadTester.DesktopGL", "BackgroundThreadTester.DesktopGL.csproj", "{8592FA21-37B6-41C8-BC7F-17EB4930B96B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BackgroundThreadTester.Android", "BackgroundThreadTester.Android.csproj", "{8592FA21-37B6-41C8-BC7F-17EB4930B96C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BackgroundThreadTester.iOS", "BackgroundThreadTester.iOS.csproj", "{8592FA21-37B6-41C8-BC7F-17EB4930B96D}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{8592FA21-37B6-41C8-BC7F-17EB4930B96A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{8592FA21-37B6-41C8-BC7F-17EB4930B96A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{8592FA21-37B6-41C8-BC7F-17EB4930B96A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{8592FA21-37B6-41C8-BC7F-17EB4930B96A}.Release|Any CPU.Build.0 = Release|Any CPU
+		{8592FA21-37B6-41C8-BC7F-17EB4930B96B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{8592FA21-37B6-41C8-BC7F-17EB4930B96B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{8592FA21-37B6-41C8-BC7F-17EB4930B96B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{8592FA21-37B6-41C8-BC7F-17EB4930B96B}.Release|Any CPU.Build.0 = Release|Any CPU
+		{8592FA21-37B6-41C8-BC7F-17EB4930B96C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{8592FA21-37B6-41C8-BC7F-17EB4930B96C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{8592FA21-37B6-41C8-BC7F-17EB4930B96C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{8592FA21-37B6-41C8-BC7F-17EB4930B96C}.Release|Any CPU.Build.0 = Release|Any CPU
+		{8592FA21-37B6-41C8-BC7F-17EB4930B96D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{8592FA21-37B6-41C8-BC7F-17EB4930B96D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{8592FA21-37B6-41C8-BC7F-17EB4930B96D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{8592FA21-37B6-41C8-BC7F-17EB4930B96D}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {0ED405E1-4605-4D5E-AB03-A426537E8EF6}
+	EndGlobalSection
+EndGlobal

+ 13 - 0
BackgroundThreadTester/Core/BackgroundThreadTester.Core.csproj

@@ -0,0 +1,13 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>net8.0</TargetFramework>
+    <RootNamespace>BackgroundThreadTester.Core</RootNamespace>
+    <AssemblyName>BackgroundThreadTester.Core</AssemblyName>
+    <LangVersion>latest</LangVersion>
+    <Nullable>enable</Nullable>
+    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+  </PropertyGroup>
+  <ItemGroup>
+    <PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.*" />
+  </ItemGroup>
+</Project>

+ 0 - 0
BackgroundThreadTester/Content/UiCursor.xnb → BackgroundThreadTester/Core/Content/UiCursor.xnb


+ 0 - 0
BackgroundThreadTester/Content/beehive.png → BackgroundThreadTester/Core/Content/beehive.png


+ 0 - 0
BackgroundThreadTester/Content/beehive.xnb → BackgroundThreadTester/Core/Content/beehive.xnb


+ 0 - 0
BackgroundThreadTester/Content/fntStandard.xnb → BackgroundThreadTester/Core/Content/fntStandard.xnb


+ 16 - 16
BackgroundThreadTester/Enums.cs → BackgroundThreadTester/Core/Enums.cs

@@ -1,16 +1,16 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace BackgroundThreadTester
-{
-    public enum MsState
-    {
-        ButtonWasPressed,
-        ButtonWasDoublePressed,
-        ButtonWasReleased,
-        ButtonStillPressed,
-        ButtonStillReleased
-    }//MsState
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace BackgroundThreadTester
+{
+    public enum MsState
+    {
+        ButtonWasPressed,
+        ButtonWasDoublePressed,
+        ButtonWasReleased,
+        ButtonStillPressed,
+        ButtonStillReleased
+    }//MsState
+}

+ 230 - 0
BackgroundThreadTester/Core/Game1.cs

@@ -0,0 +1,230 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+
+namespace BackgroundThreadTester
+{
+	public class Game1 : Game
+	{
+		GraphicsDeviceManager graphics;
+		SpriteBatch spriteBatch;
+		public TextManager aTm;
+		public InputManager cIm;
+		private SpriteFont sfStandard;
+		public MouseState mousestatus;
+		public Object aObjects;
+		TimeSpan tsElapsed = TimeSpan.Zero;
+		private String sLoading = "Loading";
+
+		// Modern async patterns
+		private CancellationTokenSource _cancellationTokenSource;
+		private readonly object _componentLock = new object();
+		private bool _backgroundTaskRunning = false;
+
+        public Game1()
+        {
+#if !__MOBILE__
+            this.IsMouseVisible = true;
+#endif
+            graphics = new GraphicsDeviceManager(this);
+            graphics.PreferredBackBufferWidth = 480;
+            graphics.PreferredBackBufferHeight = 640;
+            graphics.ApplyChanges();
+
+            Content.RootDirectory = "Content";
+
+            cIm = new InputManager(this);
+
+            CenterWindow();
+
+            // Initialize cancellation token source
+            _cancellationTokenSource = new CancellationTokenSource();
+        }
+
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing)
+			{
+				// Cancel any running background tasks
+				_cancellationTokenSource?.Cancel();
+				_cancellationTokenSource?.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		protected override void Initialize ()
+		{
+			// TODO: Add your initialization logic here
+
+			base.Initialize ();
+		}
+
+		protected override void LoadContent ()
+		{
+			// Create a new SpriteBatch, which can be used to draw textures.
+			spriteBatch = new SpriteBatch (GraphicsDevice);
+			Services.AddService (typeof(SpriteBatch), spriteBatch);
+
+			sfStandard = Content.Load<SpriteFont> ("fntStandard");
+
+			aTm = new TextManager (this, sfStandard);
+			Components.Add (aTm);
+		}
+
+		protected override void UnloadContent ()
+		{
+			// TODO: Unload any non ContentManager content here
+		}
+
+		public void CreateBackgroundThread ()
+		{
+			if (_backgroundTaskRunning)
+			{
+				Console.WriteLine("Background task already running. Cancelling previous task...");
+				_cancellationTokenSource?.Cancel();
+			}
+
+			_cancellationTokenSource = new CancellationTokenSource();
+			_backgroundTaskRunning = true;
+			
+			Console.WriteLine ("Starting modern async background task");
+			
+			// Start the modern async background task
+			_ = CreateBackgroundTaskAsync(_cancellationTokenSource.Token);
+		}
+
+		/// <summary>
+		/// Modern async background worker using Task-based async patterns
+		/// </summary>
+		private async Task CreateBackgroundTaskAsync(CancellationToken cancellationToken)
+		{
+			try
+			{
+				Console.WriteLine("Background task started");
+				
+				// Create a loop that will add 5 new components with
+				// a 2 second pause between additions
+				for (int x = 1; x <= 5; x++)
+				{
+					// Check for cancellation
+					cancellationToken.ThrowIfCancellationRequested();
+					
+					Console.WriteLine($"Adding component {x}/5");
+
+					// Schedule component addition on the main thread
+					// This is the correct cross-platform way to marshal to the UI thread
+					var testTexture = new TestTexture(this);
+					
+					// Use a thread-safe approach to add components
+					lock (_componentLock)
+					{
+						Components.Add(testTexture);
+					}
+					
+					Console.WriteLine($"Component {x} added successfully");
+					
+					// Use non-blocking delay instead of Thread.Sleep
+					// This allows the task to be cancelled during the delay
+					await Task.Delay(2000, cancellationToken);
+				}
+				
+				Console.WriteLine("Background task completed successfully");
+			}
+			catch (OperationCanceledException)
+			{
+				Console.WriteLine("Background task was cancelled");
+			}
+			catch (Exception ex)
+			{
+				Console.WriteLine($"Background task failed with error: {ex.Message}");
+			}
+			finally
+			{
+				_backgroundTaskRunning = false;
+			}
+		}
+
+		/// <summary>
+		/// Legacy method kept for compatibility - now uses modern patterns internally
+		/// </summary>
+		void BackgroundWorkerThread ()
+		{
+			// Redirect to modern async implementation
+			CreateBackgroundThread();
+		}
+
+		public int GetBackBufferWidth ()
+		{
+			return graphics.PreferredBackBufferWidth;
+		}//GetBackBufferWidth
+
+		public int GetBackBufferHeight ()
+		{
+			return graphics.PreferredBackBufferHeight;
+		}//GetBackBufferWidth
+        
+		public String GetStyleMask ()
+		{
+			return "Modern";
+		}//GetStyleMask
+
+
+		protected override void Update (GameTime gameTime)
+		{
+			mousestatus = Mouse.GetState ();
+            var keyboardState = Keyboard.GetState();
+            // Handle input
+
+            if (keyboardState.IsKeyDown(Keys.Escape))
+            {
+#if !__IOS__
+                Exit();
+#endif
+            }
+
+			cIm.InputHandler (mousestatus, gameTime);
+
+			base.Update (gameTime);
+		}
+
+		protected override void Draw (GameTime gameTime)
+		{
+            
+			GraphicsDevice.Clear (Color.CornflowerBlue);
+
+			spriteBatch.Begin (SpriteSortMode.Immediate, BlendState.AlphaBlend);
+			DrawLoadingAnimation (gameTime);
+			base.Draw (gameTime); 
+			spriteBatch.End ();
+
+       
+		}
+        
+		void DrawLoadingAnimation (GameTime gameTime)
+		{
+			tsElapsed += gameTime.ElapsedGameTime;
+
+			// it's time for next char
+			if (tsElapsed > TimeSpan.FromMilliseconds (500)) {
+				tsElapsed = TimeSpan.Zero;
+
+				sLoading = sLoading.Insert (sLoading.Length, ".");
+
+				if (sLoading.Length == 13) {
+					sLoading = "Loading";
+				}//if
+			}//if
+
+
+			spriteBatch.DrawString (sfStandard, sLoading, new Vector2 (50, 50), Color.White);
+		}//DrawLoadingAnimation
+        
+		public void CenterWindow ()
+		{
+			// Window centering is handled by the platform-specific code
+		}//CenterWindow
+	}
+}

+ 0 - 8
BackgroundThreadTester/InputManager.cs → BackgroundThreadTester/Core/InputManager.cs

@@ -1,14 +1,6 @@
 using System;
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
 using Microsoft.Xna.Framework;
 using Microsoft.Xna.Framework;
 using Microsoft.Xna.Framework.Input;
 using Microsoft.Xna.Framework.Input;
-using Microsoft.Xna.Framework.Net;
-using Microsoft.Xna.Framework.Storage;
-using Microsoft.Xna.Framework.Media;
-using System.IO;
-using Microsoft.Xna.Framework.GamerServices;
 
 
 namespace BackgroundThreadTester
 namespace BackgroundThreadTester
 {
 {

+ 72 - 80
BackgroundThreadTester/Object.cs → BackgroundThreadTester/Core/Object.cs

@@ -1,80 +1,72 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Microsoft.Xna.Framework;
-using Microsoft.Xna.Framework.Audio;
-using Microsoft.Xna.Framework.Content;
-using Microsoft.Xna.Framework.GamerServices;
-using Microsoft.Xna.Framework.Graphics;
-using Microsoft.Xna.Framework.Input;
-using Microsoft.Xna.Framework.Media;
-using Microsoft.Xna.Framework.Net;
-using Microsoft.Xna.Framework.Storage;
-
-
-namespace BackgroundThreadTester
-{
-    public class Object : Microsoft.Xna.Framework.DrawableGameComponent
-    {
-        public Vector2 pos;
-        protected Texture2D texture;
-        private Vector2 v2Temp;
-        protected Rectangle recCurrentFrame;
-        public int nAlpha;
-        public float fRotation;
-        public Vector2 vecRotationCenter;
-        private List<Rectangle> frames;
-
-        public Object(Game game, ref Texture2D theTexture)
-            : base(game)
-        {
-            texture = theTexture;
-            v2Temp = new Vector2();
-            fRotation = 0;
-            
-            pos = new Vector2();
-            pos.X = 0;
-            pos.Y = 0;
-
-            vecRotationCenter.X = 0;
-            vecRotationCenter.Y = 0;
-
-            Frames = new List<Rectangle>();
-            Rectangle frame = new Rectangle();
-
-            //Extract the frames from the texture
-            frame.X = 0;
-            frame.Y = 0;
-            frame.Width = texture.Width;
-            frame.Height = texture.Height;
-
-            Frames.Add(frame);
-        }
-
-        public override void Update(GameTime gameTime)
-        {
-            recCurrentFrame = frames[0];
-            
-            base.Update(gameTime);
-        }
-
-        public override void Draw(GameTime gameTime)
-        {
-            v2Temp.X = pos.X - (texture.Width / 2);
-            v2Temp.Y = pos.Y - texture.Height;
-
-            // Get the current spritebatch
-            SpriteBatch sBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
-
-            sBatch.Draw(texture, v2Temp, recCurrentFrame, new Color(255, 255, 255, (byte)nAlpha), fRotation, vecRotationCenter, 1f, SpriteEffects.None, 0);
-
-            base.Draw(gameTime);
-        }
-
-        public List<Rectangle> Frames
-        {
-            get { return frames; }
-            set { frames = value; }
-        }//Frames
-    }
-}
+using System;
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+
+
+namespace BackgroundThreadTester
+{
+    public class Object : Microsoft.Xna.Framework.DrawableGameComponent
+    {
+        public Vector2 pos;
+        protected Texture2D texture;
+        private Vector2 v2Temp;
+        protected Rectangle recCurrentFrame;
+        public int nAlpha;
+        public float fRotation;
+        public Vector2 vecRotationCenter;
+        private List<Rectangle> frames;
+
+        public Object(Game game, ref Texture2D theTexture)
+            : base(game)
+        {
+            texture = theTexture;
+            v2Temp = new Vector2();
+            fRotation = 0;
+            
+            pos = new Vector2();
+            pos.X = 0;
+            pos.Y = 0;
+
+            vecRotationCenter.X = 0;
+            vecRotationCenter.Y = 0;
+
+            Frames = new List<Rectangle>();
+            Rectangle frame = new Rectangle();
+
+            //Extract the frames from the texture
+            frame.X = 0;
+            frame.Y = 0;
+            frame.Width = texture.Width;
+            frame.Height = texture.Height;
+
+            Frames.Add(frame);
+        }
+
+        public override void Update(GameTime gameTime)
+        {
+            recCurrentFrame = frames[0];
+            
+            base.Update(gameTime);
+        }
+
+        public override void Draw(GameTime gameTime)
+        {
+            v2Temp.X = pos.X - (texture.Width / 2);
+            v2Temp.Y = pos.Y - texture.Height;
+
+            // Get the current spritebatch
+            SpriteBatch sBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
+
+            sBatch.Draw(texture, v2Temp, recCurrentFrame, new Color(255, 255, 255, nAlpha), fRotation, vecRotationCenter, 1f, SpriteEffects.None, 0);
+
+            base.Draw(gameTime);
+        }
+
+        public List<Rectangle> Frames
+        {
+            get { return frames; }
+            set { frames = value; }
+        }//Frames
+    }
+}

+ 0 - 0
BackgroundThreadTester/TestTexture.cs → BackgroundThreadTester/Core/TestTexture.cs


+ 0 - 9
BackgroundThreadTester/TextManager.cs → BackgroundThreadTester/Core/TextManager.cs

@@ -1,15 +1,6 @@
 using System;
 using System;
-using System.Collections.Generic;
-using System.Linq;
 using Microsoft.Xna.Framework;
 using Microsoft.Xna.Framework;
-using Microsoft.Xna.Framework.Audio;
-using Microsoft.Xna.Framework.Content;
-using Microsoft.Xna.Framework.GamerServices;
 using Microsoft.Xna.Framework.Graphics;
 using Microsoft.Xna.Framework.Graphics;
-using Microsoft.Xna.Framework.Input;
-using Microsoft.Xna.Framework.Media;
-using Microsoft.Xna.Framework.Net;
-using Microsoft.Xna.Framework.Storage;
 namespace BackgroundThreadTester
 namespace BackgroundThreadTester
 {
 {
     public class TextManager : Microsoft.Xna.Framework.DrawableGameComponent
     public class TextManager : Microsoft.Xna.Framework.DrawableGameComponent

+ 0 - 195
BackgroundThreadTester/Game1.cs

@@ -1,195 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Microsoft.Xna.Framework;
-using Microsoft.Xna.Framework.Audio;
-using Microsoft.Xna.Framework.Content;
-using Microsoft.Xna.Framework.GamerServices;
-using Microsoft.Xna.Framework.Graphics;
-using Microsoft.Xna.Framework.Input;
-using Microsoft.Xna.Framework.Media;
-using System.Windows.Forms;
-using System.Threading;
-
-using MonoMac.AppKit;
-using MonoMac.Foundation;
-
-namespace BackgroundThreadTester
-{
-	public class Game1 : Microsoft.Xna.Framework.Game
-	{
-		GraphicsDeviceManager graphics;
-		SpriteBatch spriteBatch;
-		public TextManager aTm;
-		public InputManager cIm;
-		private SpriteFont sfStandard;
-		public MouseState mousestatus;
-		public Object aObjects;
-		TimeSpan tsElapsed = TimeSpan.Zero;
-		private String sLoading = "Loading";
-
-		public Game1 ()
-		{
-			this.IsMouseVisible = true;
-			graphics = new GraphicsDeviceManager (this);
-			Content.RootDirectory = "Content";
-
-			cIm = new InputManager (this);   
-            
-			CenterWindow ();    
-		}
-
-		protected override void Initialize ()
-		{
-			// TODO: Add your initialization logic here
-
-			base.Initialize ();
-		}
-
-		protected override void LoadContent ()
-		{
-			// Create a new SpriteBatch, which can be used to draw textures.
-			spriteBatch = new SpriteBatch (GraphicsDevice);
-			Services.AddService (typeof(SpriteBatch), spriteBatch);
-
-			sfStandard = Content.Load<SpriteFont> ("fntStandard");
-
-			aTm = new TextManager (this, sfStandard);
-			Components.Add (aTm);
-		}
-
-		protected override void UnloadContent ()
-		{
-			// TODO: Unload any non ContentManager content here
-		}
-
-		public void CreateBackgroundThread ()
-		{
-			System.Console.WriteLine ("before invoke");
-			// create a new thread using BackgroundWorkerThread as method to execute
-			var thread = new Thread (BackgroundWorkerThread as ThreadStart);
-			// start it
-			thread.Start ();
-
-			System.Console.WriteLine ("after invoke");
-		}//if
-        
-		void BackgroundWorkerThread ()
-		{
-			// Create an Autorelease Pool or we will leak objects.
-			using (var pool = new NSAutoreleasePool()) {
-				// Create a loop that will add 5 new components with
-				// a 2 second pause between additions
-				Console.WriteLine ("Before component load");
-				for (int x = 1; x <= 5; x++) {
-
-					Console.WriteLine ("Before add");
-
-					// Make sure we invoke this on the Main Thread or OpenGL will throw an error
-					MonoMac.AppKit.NSApplication.SharedApplication.BeginInvokeOnMainThread (delegate {
-						Components.Add (new TestTexture (this));
-					});
-					Console.WriteLine ("After add");
-					// Sleep for 2 seconds between each component addition
-					Thread.Sleep (2000);
-
-				}
-				Console.WriteLine ("After component load");
-
-			}
-
-		}
-
-		public int GetBackBufferWidth ()
-		{
-			return graphics.PreferredBackBufferWidth;
-		}//GetBackBufferWidth
-
-		public int GetBackBufferHeight ()
-		{
-			return graphics.PreferredBackBufferHeight;
-		}//GetBackBufferWidth
-        
-		public String GetStyleMask ()
-		{
-			return this.Window.Window.StyleMask.ToString ();
-		}//GetStyleMask
-
-
-		protected override void Update (GameTime gameTime)
-		{
-			mousestatus = Mouse.GetState ();
-
-			cIm.InputHandler (mousestatus, gameTime);
-
-			base.Update (gameTime);
-		}
-
-		protected override void Draw (GameTime gameTime)
-		{
-            
-			GraphicsDevice.Clear (Color.CornflowerBlue);
-
-			spriteBatch.Begin (SpriteSortMode.Immediate, BlendState.AlphaBlend);
-			DrawLoadingAnimation (gameTime);
-			base.Draw (gameTime); 
-			spriteBatch.End ();
-
-       
-		}
-        
-		void DrawLoadingAnimation (GameTime gameTime)
-		{
-			tsElapsed += gameTime.ElapsedGameTime;
-
-			// it's time for next char
-			if (tsElapsed > TimeSpan.FromMilliseconds (500)) {
-				tsElapsed = TimeSpan.Zero;
-
-				sLoading = sLoading.Insert (sLoading.Length, ".");
-
-				if (sLoading.Length == 13) {
-					sLoading = "Loading";
-				}//if
-			}//if
-
-
-			spriteBatch.DrawString (sfStandard, sLoading, new Vector2 (50, 50), Color.White);
-		}//DrawLoadingAnimation
-        
-		public void CenterWindow ()
-		{
-        	
-        		
-			int index;
-			int upperBound;
-			float fScreenWidth, fScreenHeight, fNewX, fNewY, fWindowWidth, fWindowHeight, fTitleBarHeight;
-			Screen[] screens = Screen.AllScreens;
-	        
-			fScreenWidth = fScreenHeight = 0;
-	        
-			upperBound = screens.GetUpperBound (0);
-			for (index = 0; index <= upperBound; index++) {
-				if (screens [index].Primary) {
-					fScreenWidth = (float)screens [index].Bounds.Width;
-					fScreenHeight = (float)screens [index].Bounds.Height;  
-					index = upperBound;
-				}//if
-			}//for
-            
-			fWindowWidth = graphics.PreferredBackBufferWidth;
-			fWindowHeight = graphics.PreferredBackBufferHeight;
-            	
-			fNewX = (fScreenWidth - fWindowWidth) / 2;
-			fNewY = (fScreenHeight - fWindowHeight) / 2;
-            
-			fTitleBarHeight = this.Window.Window.Frame.Height - fWindowHeight;
-            
-			System.Drawing.PointF pfLocation = new System.Drawing.PointF (fNewX, fNewY);
-			System.Drawing.PointF pfSize = new System.Drawing.PointF (fWindowWidth, fWindowHeight + fTitleBarHeight);
-			System.Drawing.SizeF sfSize = new System.Drawing.SizeF (pfSize);
-			System.Drawing.RectangleF rectTemp = new System.Drawing.RectangleF (pfLocation, sfSize);
-			this.Window.Window.SetFrame (rectTemp, true);
-		}//CenterWindow
-	}
-}

+ 0 - 18
BackgroundThreadTester/Info.plist

@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>CFBundleIdentifier</key>
-	<string>com.yourcompany.BackgroundThreadTester</string>
-	<key>CFBundleName</key>
-	<string>BackgroundThreadTester</string>
-	<key>CFBundleVersion</key>
-	<string>1</string>
-	<key>LSMinimumSystemVersion</key>
-	<string>10.6</string>
-	<key>NSMainNibFile</key>
-	<string>MainMenu</string>
-	<key>NSPrincipalClass</key>
-	<string>NSApplication</string>
-</dict>
-</plist>

+ 0 - 118
BackgroundThreadTester/MainMenu.xib

@@ -1,118 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
-	<data>
-		<int key="IBDocument.SystemTarget">1060</int>
-		<string key="IBDocument.SystemVersion">10D573</string>
-		<string key="IBDocument.InterfaceBuilderVersion">762</string>
-		<string key="IBDocument.AppKitVersion">1038.29</string>
-		<string key="IBDocument.HIToolboxVersion">460.00</string>
-		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
-			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
-			<string key="NS.object.0">762</string>
-		</object>
-		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
-			<bool key="EncodedWithXMLCoder">YES</bool>
-		</object>
-		<object class="NSArray" key="IBDocument.PluginDependencies">
-			<bool key="EncodedWithXMLCoder">YES</bool>
-			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-		</object>
-		<object class="NSMutableDictionary" key="IBDocument.Metadata">
-			<bool key="EncodedWithXMLCoder">YES</bool>
-			<object class="NSArray" key="dict.sortedKeys" id="0">
-				<bool key="EncodedWithXMLCoder">YES</bool>
-			</object>
-			<object class="NSMutableArray" key="dict.values">
-				<bool key="EncodedWithXMLCoder">YES</bool>
-			</object>
-		</object>
-		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
-			<bool key="EncodedWithXMLCoder">YES</bool>
-			<object class="NSCustomObject" id="1001">
-				<string key="NSClassName">NSObject</string>
-			</object>
-			<object class="NSCustomObject" id="1003">
-				<string key="NSClassName">FirstResponder</string>
-			</object>
-			<object class="NSCustomObject" id="1004">
-				<string key="NSClassName">NSApplication</string>
-			</object>
-		</object>
-		<object class="IBObjectContainer" key="IBDocument.Objects">
-			<object class="NSMutableArray" key="connectionRecords">
-				<bool key="EncodedWithXMLCoder">YES</bool>
-			</object>
-			<object class="IBMutableOrderedSet" key="objectRecords">
-				<object class="NSArray" key="orderedObjects">
-					<bool key="EncodedWithXMLCoder">YES</bool>
-					<object class="IBObjectRecord">
-						<int key="objectID">0</int>
-						<reference key="object" ref="0" />
-						<reference key="children" ref="1000" />
-						<nil key="parent" />
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">-2</int>
-						<reference key="object" ref="1001" />
-						<reference key="parent" ref="0" />
-						<string key="objectName">File's Owner</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">-1</int>
-						<reference key="object" ref="1003" />
-						<reference key="parent" ref="0" />
-						<string key="objectName">First Responder</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">-3</int>
-						<reference key="object" ref="1004" />
-						<reference key="parent" ref="0" />
-						<string key="objectName">Application</string>
-					</object>
-				</object>
-			</object>
-			<object class="NSMutableDictionary" key="flattenedProperties">
-				<bool key="EncodedWithXMLCoder">YES</bool>
-				<object class="NSArray" key="dict.sortedKeys">
-					<bool key="EncodedWithXMLCoder">YES</bool>
-					<string>-1.IBPluginDependency</string>
-					<string>-2.IBPluginDependency</string>
-					<string>-3.IBPluginDependency</string>
-				</object>
-				<object class="NSMutableArray" key="dict.values">
-					<bool key="EncodedWithXMLCoder">YES</bool>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-				</object>
-			</object>
-			<object class="NSMutableDictionary" key="unlocalizedProperties">
-				<bool key="EncodedWithXMLCoder">YES</bool>
-				<reference key="dict.sortedKeys" ref="0" />
-				<object class="NSMutableArray" key="dict.values">
-					<bool key="EncodedWithXMLCoder">YES</bool>
-				</object>
-			</object>
-			<nil key="activeLocalization" />
-			<object class="NSMutableDictionary" key="localizations">
-				<bool key="EncodedWithXMLCoder">YES</bool>
-				<reference key="dict.sortedKeys" ref="0" />
-				<object class="NSMutableArray" key="dict.values">
-					<bool key="EncodedWithXMLCoder">YES</bool>
-				</object>
-			</object>
-			<nil key="sourceID" />
-			<int key="maxID">0</int>
-		</object>
-		<object class="IBClassDescriber" key="IBDocument.Classes" />
-		<int key="IBDocument.localizationMode">0</int>
-		<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
-		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
-			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
-			<integer value="3000" key="NS.object.0" />
-		</object>
-		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
-		<nil key="IBDocument.LastKnownRelativeProjectPath" />
-		<int key="IBDocument.defaultPropertyAccessControl">3</int>
-	</data>
-</archive>

+ 12 - 0
BackgroundThreadTester/Platforms/Android/AndroidManifest.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.companyname.backgroundthreadtester">
+	<application android:label="BackgroundThreadTester" android:icon="@mipmap/ic_launcher">
+		<activity android:name=".MainActivity">
+			<intent-filter>
+				<action android:name="android.intent.action.MAIN" />
+				<category android:name="android.intent.category.LAUNCHER" />
+			</intent-filter>
+		</activity>
+	</application>
+	<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
+</manifest>

+ 16 - 0
BackgroundThreadTester/Platforms/Android/BackgroundThreadTester.Android.csproj

@@ -0,0 +1,16 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>net8.0-android</TargetFramework>
+    <RootNamespace>BackgroundThreadTester.Android</RootNamespace>
+    <AssemblyName>BackgroundThreadTester.Android</AssemblyName>
+    <Nullable>enable</Nullable>
+    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\BackgroundThreadTester.Core.csproj" />
+    <PackageReference Include="MonoGame.Framework.Android" Version="3.8.*" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="..\..\Core\Content\**" CopyToOutputDirectory="PreserveNewest" />
+  </ItemGroup>
+</Project>

+ 20 - 0
BackgroundThreadTester/Platforms/Android/Program.cs

@@ -0,0 +1,20 @@
+using Android.App;
+using Android.Content.PM;
+using Android.OS;
+using Android.Views;
+using Microsoft.Xna.Framework;
+
+namespace BackgroundThreadTester
+{
+    [Activity(Label = "BackgroundThreadTester", MainLauncher = true, Icon = "@drawable/icon", Theme = "@style/Theme.Splash", AlwaysRetainTaskState = true, LaunchMode = LaunchMode.SingleInstance, ScreenOrientation = ScreenOrientation.FullUser, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.ScreenSize | ConfigChanges.ScreenLayout)]
+    public class Activity1 : AndroidGameActivity
+    {
+        protected override void OnCreate(Bundle bundle)
+        {
+            base.OnCreate(bundle);
+            var g = new Game1();
+            SetContentView((View)g.Services.GetService(typeof(View)));
+            g.Run();
+        }
+    }
+}

+ 17 - 0
BackgroundThreadTester/Platforms/DesktopGL/BackgroundThreadTester.DesktopGL.csproj

@@ -0,0 +1,17 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net8.0</TargetFramework>
+    <RootNamespace>BackgroundThreadTester.DesktopGL</RootNamespace>
+    <AssemblyName>BackgroundThreadTester.DesktopGL</AssemblyName>
+    <Nullable>enable</Nullable>
+    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\BackgroundThreadTester.Core.csproj" />
+    <PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.*" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="..\..\Core\Content\**" CopyToOutputDirectory="PreserveNewest" />
+  </ItemGroup>
+</Project>

+ 14 - 0
BackgroundThreadTester/Platforms/DesktopGL/Program.cs

@@ -0,0 +1,14 @@
+using System;
+
+namespace BackgroundThreadTester
+{
+    public static class Program
+    {
+        [STAThread]
+        static void Main()
+        {
+            using (var game = new Game1())
+                game.Run();
+        }
+    }
+}

+ 18 - 0
BackgroundThreadTester/Platforms/Windows/BackgroundThreadTester.Windows.csproj

@@ -0,0 +1,18 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>WinExe</OutputType>
+    <TargetFramework>net8.0-windows</TargetFramework>
+    <RootNamespace>BackgroundThreadTester.Windows</RootNamespace>
+    <AssemblyName>BackgroundThreadTester.Windows</AssemblyName>
+    <UseWindowsForms>true</UseWindowsForms>
+    <Nullable>enable</Nullable>
+    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\BackgroundThreadTester.Core.csproj" />
+    <PackageReference Include="MonoGame.Framework.WindowsDX" Version="3.8.*" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="..\..\Core\Content\**" CopyToOutputDirectory="PreserveNewest" />
+  </ItemGroup>
+</Project>

+ 17 - 0
BackgroundThreadTester/Platforms/Windows/Program.cs

@@ -0,0 +1,17 @@
+using System;
+using BackgroundThreadTester;
+
+namespace BackgroundThreadTester.Windows
+{
+    public static class Program
+    {
+        [STAThread]
+        public static void Main()
+        {
+            using (var game = new Game1())
+            {
+                game.Run();
+            }
+        }
+    }
+}

+ 16 - 0
BackgroundThreadTester/Platforms/iOS/BackgroundThreadTester.iOS.csproj

@@ -0,0 +1,16 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>net8.0-ios</TargetFramework>
+    <RootNamespace>BackgroundThreadTester.iOS</RootNamespace>
+    <AssemblyName>BackgroundThreadTester.iOS</AssemblyName>
+    <Nullable>enable</Nullable>
+    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\BackgroundThreadTester.Core.csproj" />
+    <PackageReference Include="MonoGame.Framework.iOS" Version="3.8.*" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="..\..\Core\Content\**" CopyToOutputDirectory="PreserveNewest" />
+  </ItemGroup>
+</Project>

+ 22 - 0
BackgroundThreadTester/Platforms/iOS/Info.plist

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+    <key>CFBundleDisplayName</key>
+    <string>BackgroundThreadTester</string>
+    <key>CFBundleIdentifier</key>
+    <string>com.companyname.backgroundthreadtester</string>
+    <key>CFBundleVersion</key>
+    <string>1.0</string>
+    <key>CFBundleShortVersionString</key>
+    <string>1.0</string>
+    <key>UILaunchStoryboardName</key>
+    <string>LaunchScreen</string>
+    <key>UISupportedInterfaceOrientations</key>
+    <array>
+        <string>UIInterfaceOrientationPortrait</string>
+        <string>UIInterfaceOrientationLandscapeLeft</string>
+        <string>UIInterfaceOrientationLandscapeRight</string>
+    </array>
+</dict>
+</plist>

+ 30 - 0
BackgroundThreadTester/Platforms/iOS/Program.cs

@@ -0,0 +1,30 @@
+using Foundation;
+using UIKit;
+
+namespace BackgroundThreadTester
+{
+    [Register("AppDelegate")]
+    class Program : UIApplicationDelegate
+    {
+        private static Game1 game;
+
+        internal static void RunGame()
+        {
+            game = new Game1();
+            game.Run();
+        }
+
+        /// <summary>
+        /// The main entry point for the application.
+        /// </summary>
+        static void Main(string[] args)
+        {
+            UIApplication.Main(args, null, "AppDelegate");
+        }
+
+        public override void FinishedLaunching(UIApplication app)
+        {
+            RunGame();
+        }
+    }
+}

+ 0 - 67
BackgroundThreadTester/Program.cs

@@ -1,67 +0,0 @@
-using MonoMac.AppKit;
-using MonoMac.Foundation;
-
-
-namespace BackgroundThreadTester
-{
-	class Program
-	{
-		static void Main (string [] args)
-		{
-			NSApplication.Init ();
-			
-			using (var p = new NSAutoreleasePool ()) {
-				NSApplication.SharedApplication.Delegate = new AppDelegate();
-				NSApplication.Main(args);
-			}
-		}
-	}
-	
-	
-	class AppDelegate : NSApplicationDelegate
-	{
-		Game1 game; 
-		
-		public override void FinishedLaunching (MonoMac.Foundation.NSObject notification)
-		{			
-			game = new Game1();
-			game.Run();
-		}
-		
-		public override bool ApplicationShouldTerminateAfterLastWindowClosed (NSApplication sender)
-		{
-			return true;
-		}
-		
-		public override NSApplicationTerminateReply ApplicationShouldTerminate (NSApplication sender)
-		{
-
-
-				
-				NSAlert alert = NSAlert.WithMessage("Warning", "Yes", "No", null, "Do you really want to close?");
-				
-				var button = alert.RunModal();
-				
-				if ( button == 0 )
-				{
-					return NSApplicationTerminateReply.Cancel;		
-				}//if
-				else
-				{
-					return NSApplicationTerminateReply.Now;
-				}//else
-
-		}
-		
-		
-
-
-
-
-	}
-	
-	
-	
-
-}
-

+ 131 - 5
BackgroundThreadTester/README.md

@@ -1,15 +1,141 @@
-BackgroundThreadSample
-======================
+# Background Thread Tester - MonoGame 3.8.4
 
 
-This sample demonstrates the loading of assets in a background thread.
+This project demonstrates background thread management in MonoGame applications.
+
+## Project Structure
+
+This project has been modernized to use SDK-style projects with MonoGame 3.8.4 NuGet packages:
+
+- **BackgroundThreadTester.Windows.csproj** - Windows DirectX version (net8.0-windows)
+- **BackgroundThreadTester.DesktopGL.csproj** - Cross-platform OpenGL version (net8.0)
+- **BackgroundThreadTester.Android.csproj** - Android version (net8.0-android)
+- **BackgroundThreadTester.iOS.csproj** - iOS version (net8.0-ios)
+
+## Building and Running
+
+### Prerequisites
+- .NET 8.0 SDK or later
+- Visual Studio 2022 or VS Code
+
+### Build Commands
+```bash
+# Windows version
+dotnet build BackgroundThreadTester.Windows.csproj
+
+# DesktopGL version
+dotnet build BackgroundThreadTester.DesktopGL.csproj
+
+# Android version (requires Android SDK)
+dotnet build BackgroundThreadTester.Android.csproj
+```
+
+### Run Commands
+```bash
+# Windows version
+dotnet run --project BackgroundThreadTester.Windows.csproj
+
+# DesktopGL version
+dotnet run --project BackgroundThreadTester.DesktopGL.csproj
+```
+
+### VS Code Support
+The project includes `.vscode/tasks.json` and `.vscode/launch.json` for building and debugging in VS Code.
+
+**Available VS Code configurations:**
+- **Launch Windows** - Debug Windows version with internal console
+- **Launch DesktopGL** - Debug DesktopGL version with internal console  
+- **Launch Windows (External Console)** - Run Windows version with external terminal
+- **Launch DesktopGL (External Console)** - Run DesktopGL version with external terminal
+
+**Quick Start:**
+1. Press `F5` to start debugging
+2. Select a launch configuration
+3. Set breakpoints by clicking in the left margin
+
+📖 **Troubleshooting**: See `VSCODE_LAUNCH_GUIDE.md` for detailed setup and troubleshooting instructions.
+
+### Visual Studio Support
+Open `BackgroundThreadTester.sln` in Visual Studio 2022.
+
+## Features
+
+- **Modern Async Background Tasks** - Uses Task-based async/await patterns instead of raw Thread
+- **Cross-Platform Thread Safety** - Proper thread marshaling for UI operations across all platforms
+- **Cancellation Support** - Background tasks can be cancelled cooperatively using CancellationToken
+- **Error Handling** - Comprehensive exception handling with try/catch blocks
+- **Non-Blocking Operations** - Uses Task.Delay() instead of Thread.Sleep() for better responsiveness
+- **Thread-Safe Component Management** - Uses locks for safe component addition from background threads
+- **Resource Cleanup** - Proper disposal of background task resources
+- Cross-platform compatibility
+- Uses existing .xnb content files (no .mgcb pipeline needed)
+
+## Modern Threading Patterns Used
+
+This project demonstrates modern .NET threading best practices:
+
+### ✅ Task-Based Async Pattern
+```csharp
+// Modern approach using async/await
+private async Task CreateBackgroundTaskAsync(CancellationToken cancellationToken)
+{
+    await Task.Delay(2000, cancellationToken); // Non-blocking delay
+}
+```
+
+### ✅ Cooperative Cancellation
+```csharp
+// Cancellation token support
+cancellationToken.ThrowIfCancellationRequested();
+```
+
+### ✅ Thread-Safe Operations
+```csharp
+// Thread-safe component addition
+lock (_componentLock)
+{
+    Components.Add(testTexture);
+}
+```
+
+### ✅ Exception Handling
+```csharp
+try {
+    // Background work
+} catch (OperationCanceledException) {
+    // Handle cancellation
+} catch (Exception ex) {
+    // Handle other errors
+}
+```
+
+### ❌ Legacy Patterns (Avoided)
+- Direct Thread usage with Thread.Start()
+- Thread.Sleep() blocking calls
+- Unsafe cross-thread operations
+- No cancellation support
+- No error handling
+
+## Original Description
 
 
 Sample originally created by CircleOf14 and modified by Kenneth Pouncey to create new textures to be added
 Sample originally created by CircleOf14 and modified by Kenneth Pouncey to create new textures to be added
 to the game components dynamically in the background.
 to the game components dynamically in the background.
 
 
 Of special interest look at the following methods:
 Of special interest look at the following methods:
 
 
-CreateBackgroundThread () - Creates a thread to be executed in the background and starts it.
-BackgroundWorkerThread () - Worker thread that actually does the work of creating the new asset and adding
+- `CreateBackgroundThread()` - Creates a modern async background task with cancellation support
+- `CreateBackgroundTaskAsync()` - **NEW** Modern async worker using Task-based patterns with proper error handling
+- `BackgroundWorkerThread()` - Legacy method (now redirects to modern implementation for compatibility)
+
+### Key Modern Improvements:
+1. **Async/Await Pattern**: Uses `Task.Delay()` instead of `Thread.Sleep()` for non-blocking operations
+2. **Cancellation Support**: All background operations can be cancelled using `CancellationToken`
+3. **Thread Safety**: Components are added using thread-safe locking mechanisms
+4. **Error Handling**: Comprehensive exception handling for robust operation
+5. **Resource Management**: Proper cleanup and disposal of background task resources
+6. **Cross-Platform**: Works consistently across Windows, DesktopGL, Android, and iOS
 
 
 Make sure to read the comments in these two methods.
 Make sure to read the comments in these two methods.
 
 
+## MonoGame Version
+This project uses MonoGame 3.8.* NuGet packages for better dependency management and cross-platform support.
+