diff --git a/XRTK-Core/Packages/com.xrtk.core/Services/BaseEventSystem.cs b/XRTK-Core/Packages/com.xrtk.core/Services/BaseEventSystem.cs index 784c68f52..ed80df0d7 100644 --- a/XRTK-Core/Packages/com.xrtk.core/Services/BaseEventSystem.cs +++ b/XRTK-Core/Packages/com.xrtk.core/Services/BaseEventSystem.cs @@ -27,7 +27,6 @@ protected BaseEventSystem(BaseMixedRealityProfile profile) #region IMixedRealityEventSystem Implementation private static int eventExecutionDepth = 0; - private readonly WaitUntil doneExecutingEvents = new WaitUntil(() => eventExecutionDepth == 0); /// public List EventListeners { get; } = new List(); @@ -53,7 +52,7 @@ public virtual async void Register(GameObject listener) if (eventExecutionDepth > 0) { - await doneExecutingEvents; + await eventExecutionDepth.WaitUntil(depth => depth == 0); } EventListeners.Add(listener); @@ -66,7 +65,7 @@ public virtual async void Unregister(GameObject listener) if (eventExecutionDepth > 0) { - await doneExecutingEvents; + await eventExecutionDepth.WaitUntil(depth => depth == 0); } EventListeners.Remove(listener); diff --git a/XRTK-Core/Packages/com.xrtk.core/Utilities/Async/Awaiters.cs b/XRTK-Core/Packages/com.xrtk.core/Utilities/Async/Awaiters.cs index 6ad608a89..61d7dcdd4 100644 --- a/XRTK-Core/Packages/com.xrtk.core/Utilities/Async/Awaiters.cs +++ b/XRTK-Core/Packages/com.xrtk.core/Utilities/Async/Awaiters.cs @@ -48,46 +48,74 @@ public static class Awaiters /// Author: Oguzhan Soykan /// Source: https://stackoverflow.com/questions/29089417/c-sharp-wait-until-condition-is-true /// + /// Passing in -1 will make this wait indefinitely for the condition to be met. /// /// /// The predicate condition to meet. - /// The number of seconds before timing out and throwing an exception. + /// The number of seconds before timing out and throwing an exception. (-1 is indefinite) + /// ReSharper disable once ExceptionNotThrown /// A can be thrown when the condition isn't satisfied after timeout. public static async Task WaitUntil(this T element, Func predicate, int timeout = 10) { - using (var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(timeout))) + if (timeout == -1) { - var tcs = new TaskCompletionSource(); - - void Exception() + await WaitUntil_Indefinite(element, predicate); + } + else + { + using (var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(timeout))) { - tcs.TrySetException(new TimeoutException()); - tcs.TrySetCanceled(); - } + var tcs = new TaskCompletionSource(); - cancellationTokenSource.Token.Register(Exception); + void Exception() + { + tcs.TrySetException(new TimeoutException()); + tcs.TrySetCanceled(); + } - while (!cancellationTokenSource.IsCancellationRequested) - { - try + cancellationTokenSource.Token.Register(Exception); + + while (!cancellationTokenSource.IsCancellationRequested) { - if (!predicate(element)) + try { - await Task.Delay(1, cancellationTokenSource.Token); - continue; + if (!predicate(element)) + { + await Task.Delay(1, cancellationTokenSource.Token); + continue; + } } - } - catch (Exception e) - { - tcs.TrySetException(e); + catch (Exception e) + { + tcs.TrySetException(e); + } + + tcs.TrySetResult(Task.CompletedTask); + break; } - tcs.TrySetResult(Task.CompletedTask); - break; + await tcs.Task; } + } + } + + private static async Task WaitUntil_Indefinite(T element, Func predicate) + { + var tcs = new TaskCompletionSource(); - await tcs.Task; + while (true) + { + if (!predicate(element)) + { + await Task.Delay(1); + continue; + } + + tcs.TrySetResult(Task.CompletedTask); + break; } + + await tcs.Task; } } }