Example #1
0
        /// <summary>
        ///  Creates an autorun that observes and runs the given predicate until it returns true.
        ///  Once that happens, the given effect is executed and the autorunner is disposed.
        ///  The function returns a disposer to cancel the autorunner prematurely.
        /// </summary>
        /// <param name="sharedState">The shared state to use.</param>
        /// <param name="predicate">The predicate to match.</param>
        /// <param name="cancellationToken">The cancellation token to cancel the operation.</param>
        /// <param name="whenOptions">The options for this When.</param>
        /// <returns>A task to await in asynchronous code..</returns>
        public static Task When(this ISharedState sharedState, Func <bool> predicate, CancellationToken cancellationToken, WhenOptions whenOptions = null)
        {
            if (whenOptions != null && whenOptions.ErrorHandler != null)
            {
                throw new InvalidOperationException(Resources.NoErrorHandlerWithWhen);
            }
            else if (whenOptions is null)
            {
                whenOptions = new WhenOptions();
            }

            var taskScheduler        = sharedState.GetTaskScheduler();
            var taskCompletionSource = new TaskCompletionSource <bool>();

            whenOptions.ErrorHandler = (ex) => taskCompletionSource.SetException(ex);

#pragma warning disable CA2000 // Dispose objects before losing scope
            IDisposable when = When(sharedState, predicate, () => taskCompletionSource.SetResult(true), whenOptions);
#pragma warning restore CA2000 // Dispose objects before losing scope

            var cancellationTokenRegistration = cancellationToken.Register(() =>
            {
                when.Dispose();
                taskCompletionSource.TrySetCanceled();
            });

            return(taskCompletionSource.Task.ContinueWith(
                       t =>
            {
                cancellationTokenRegistration.Dispose();
            }, taskScheduler));
        }
Example #2
0
        /// <summary>
        ///  Creates an autorun that observes and runs the given predicate until it returns true.
        ///  Once that happens, the given effect is executed and the autorunner is disposed.
        ///  The function returns a disposer to cancel the autorunner prematurely.
        /// </summary>
        /// <param name="sharedState">The shared state to use.</param>
        /// <param name="predicate">The predicate to match.</param>
        /// <param name="effect">The effect to run.</param>
        /// <param name="whenOptions">The options for this When.</param>
        /// <returns>A disposer to cancel the autorunner prematurely.</returns>
        public static IDisposable When(this ISharedState sharedState, Func <bool> predicate, Action effect, WhenOptions whenOptions = null)
        {
            if (sharedState is null)
            {
                throw new ArgumentNullException(nameof(sharedState));
            }

            if (predicate is null)
            {
                throw new ArgumentNullException(nameof(predicate));
            }

            if (effect is null)
            {
                throw new ArgumentNullException(nameof(effect));
            }

            if (whenOptions is null)
            {
                whenOptions = new WhenOptions();
            }

            IDisposable             result   = null;
            Reaction                reaction = null;
            CancellationTokenSource cancellationTokenSource = null;

            whenOptions.Name = !string.IsNullOrEmpty(whenOptions.Name) ? whenOptions.Name : $"When@{sharedState.GetUniqueId()}";

            if (whenOptions.TimeOut.HasValue)
            {
#pragma warning disable CA2000 // Dispose objects before losing scope
                cancellationTokenSource = new CancellationTokenSource();
#pragma warning restore CA2000 // Dispose objects before losing scope

                var taskScheduler = sharedState.GetTaskScheduler();
                Task.Factory.StartNew(
                    async() =>
                {
                    var token = cancellationTokenSource.Token;
                    await Task.Delay(whenOptions.TimeOut.Value, token).ConfigureAwait(true);
                    if (!token.IsCancellationRequested)
                    {
                        throw new TimeoutException(
                            string.Format(CultureInfo.CurrentCulture, Resources.TimeoutOccuredInWhen, whenOptions.Name, whenOptions.TimeOut.Value));
                    }
                },
                    CancellationToken.None,
                    TaskCreationOptions.DenyChildAttach,
                    taskScheduler).Unwrap().ContinueWith(
                    t =>
                {
                    try
                    {
                        if (t.Exception != null)
                        {
                            reaction.ReportExceptionInReaction(t.Exception);
                        }
                    }
                    finally
                    {
                        cancellationTokenSource.Dispose();
                        result.Dispose();
                    }
                }, taskScheduler);
            }

            var autorunOptions = new AutorunOptions()
            {
                Name = $"{whenOptions.Name}-effect",
                RequiresObservable = whenOptions.RequiresObservable,
            };

            if (whenOptions.ErrorHandler != null)
            {
                autorunOptions.ErrorHandler = (r, e) => whenOptions.ErrorHandler(e);
            }

#pragma warning disable CA2000 // Dispose objects before losing scope
            result = sharedState.Autorun(
                r =>
            {
                reaction = r;
                if (predicate())
                {
                    r.Dispose();
                    cancellationTokenSource?.Cancel();
                    effect();
                }
            }, autorunOptions);
#pragma warning restore CA2000 // Dispose objects before losing scope

            return(new DelegateDisposable(() =>
            {
                result.Dispose();
                cancellationTokenSource?.Cancel();
            }));
        }
Example #3
0
 /// <summary>
 ///  Creates an autorun that observes and runs the given predicate until it returns true.
 ///  Once that happens, the given effect is executed and the autorunner is disposed.
 ///  The function returns a disposer to cancel the autorunner prematurely.
 /// </summary>
 /// <param name="sharedState">The shared state to use.</param>
 /// <param name="predicate">The predicate to match.</param>
 /// <param name="whenOptions">The options for this When.</param>
 /// <returns>A task to await in asynchronous code..</returns>
 public static Task When(this ISharedState sharedState, Func <bool> predicate, WhenOptions whenOptions = null)
 {
     return(sharedState.When(predicate, CancellationToken.None, whenOptions));
 }