diff --git a/build/Base.props b/build/Base.props
index a8702d32a8..a60373ebb3 100644
--- a/build/Base.props
+++ b/build/Base.props
@@ -1,10 +1,5 @@
-
-
diff --git a/src/Avalonia.Base/Utilities/SynchronousCompletionAsyncResult.cs b/src/Avalonia.Base/Utilities/SynchronousCompletionAsyncResult.cs
new file mode 100644
index 0000000000..f321b2b2f1
--- /dev/null
+++ b/src/Avalonia.Base/Utilities/SynchronousCompletionAsyncResult.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace Avalonia.Utilities
+{
+ ///
+ /// A task-like operation that is guaranteed to finish continuations synchronously,
+ /// can be used for parametrized one-shot events
+ ///
+ public struct SynchronousCompletionAsyncResult : INotifyCompletion
+ {
+ private readonly SynchronousCompletionAsyncResultSource _source;
+ private readonly T _result;
+ private readonly bool _isValid;
+ internal SynchronousCompletionAsyncResult(SynchronousCompletionAsyncResultSource source)
+ {
+ _source = source;
+ _result = default;
+ _isValid = true;
+ }
+
+ public SynchronousCompletionAsyncResult(T result)
+ {
+ _result = result;
+ _source = null;
+ _isValid = true;
+ }
+
+ static void ThrowNotInitialized() =>
+ throw new InvalidOperationException("This SynchronousCompletionAsyncResult was not initialized");
+
+ public bool IsCompleted
+ {
+ get
+ {
+ if (!_isValid)
+ ThrowNotInitialized();
+ return _source == null || _source.IsCompleted;
+ }
+ }
+
+ public T GetResult()
+ {
+ if (!_isValid)
+ ThrowNotInitialized();
+ return _source == null ? _result : _source.Result;
+ }
+
+
+ public void OnCompleted(Action continuation)
+ {
+ if (!_isValid)
+ ThrowNotInitialized();
+ if (_source == null)
+ continuation();
+ else
+ _source.OnCompleted(continuation);
+ }
+
+ public SynchronousCompletionAsyncResult GetAwaiter() => this;
+ }
+
+ ///
+ /// Source for incomplete SynchronousCompletionAsyncResult
+ ///
+ ///
+ public class SynchronousCompletionAsyncResultSource
+ {
+ private T _result;
+ internal bool IsCompleted { get; private set; }
+ public SynchronousCompletionAsyncResult AsyncResult => new SynchronousCompletionAsyncResult(this);
+
+ internal T Result => IsCompleted ?
+ _result :
+ throw new InvalidOperationException("Asynchronous operation is not yet completed");
+
+ private List _continuations;
+
+ internal void OnCompleted(Action continuation)
+ {
+ if(_continuations==null)
+ _continuations = new List();
+ _continuations.Add(continuation);
+ }
+
+ public void SetResult(T result)
+ {
+ if (IsCompleted)
+ throw new InvalidOperationException("Asynchronous operation is already completed");
+ _result = result;
+ IsCompleted = true;
+ if(_continuations!=null)
+ foreach (var c in _continuations)
+ c();
+ _continuations = null;
+ }
+
+ public void TrySetResult(T result)
+ {
+ if(IsCompleted)
+ return;
+ SetResult(result);
+ }
+ }
+}
diff --git a/src/Avalonia.Styling/Controls/ChildNameScope.cs b/src/Avalonia.Styling/Controls/ChildNameScope.cs
index c3c3109502..e6707e71db 100644
--- a/src/Avalonia.Styling/Controls/ChildNameScope.cs
+++ b/src/Avalonia.Styling/Controls/ChildNameScope.cs
@@ -1,4 +1,5 @@
using System.Threading.Tasks;
+using Avalonia.Utilities;
namespace Avalonia.Controls
{
@@ -14,27 +15,45 @@ namespace Avalonia.Controls
public void Register(string name, object element) => _inner.Register(name, element);
- public ValueTask