diff --git a/Ryujinx.Memory/Tracking/RegionHandle.cs b/Ryujinx.Memory/Tracking/RegionHandle.cs
index 2df02f1e..40deba98 100644
--- a/Ryujinx.Memory/Tracking/RegionHandle.cs
+++ b/Ryujinx.Memory/Tracking/RegionHandle.cs
@@ -35,6 +35,7 @@ namespace Ryujinx.Memory.Tracking
 
         private event Action _onDirty;
 
+        private object _preActionLock = new object();
         private RegionSignal _preAction; // Action to perform before a read or write. This will block the memory access.
         private readonly List<VirtualRegion> _regions;
         private readonly MemoryTracking _tracking;
@@ -115,17 +116,16 @@ namespace Ryujinx.Memory.Tracking
         /// <param name="write">Whether the region was written to or read</param>
         internal void Signal(ulong address, ulong size, bool write, ref IList<RegionHandle> handleIterable)
         {
-            RegionSignal action = Interlocked.Exchange(ref _preAction, null);
-
             // If this handle was already unmapped (even if just partially),
             // then we have nothing to do until it is mapped again.
             // The pre-action should be still consumed to avoid flushing on remap.
             if (Unmapped)
             {
+                Interlocked.Exchange(ref _preAction, null);
                 return;
             }
 
-            if (action != null)
+            if (_preAction != null)
             {
                 // Copy the handles list in case it changes when we're out of the lock.
                 if (handleIterable is List<RegionHandle>)
@@ -138,7 +138,12 @@ namespace Ryujinx.Memory.Tracking
 
                 try
                 {
-                    action.Invoke(address, size);
+                    lock (_preActionLock)
+                    {
+                        _preAction?.Invoke(address, size);
+
+                        _preAction = null;
+                    }
                 }
                 finally
                 {
@@ -220,14 +225,19 @@ namespace Ryujinx.Memory.Tracking
         {
             ClearVolatile();
 
-            RegionSignal lastAction = Interlocked.Exchange(ref _preAction, action);
-            if (lastAction == null && action != lastAction)
+            lock (_preActionLock)
             {
-                lock (_tracking.TrackingLock)
+                RegionSignal lastAction = _preAction;
+                _preAction = action;
+
+                if (lastAction == null && action != lastAction)
                 {
-                    foreach (VirtualRegion region in _regions)
+                    lock (_tracking.TrackingLock)
                     {
-                        region.UpdateProtection();
+                        foreach (VirtualRegion region in _regions)
+                        {
+                            region.UpdateProtection();
+                        }
                     }
                 }
             }