Пример #1
0
        /// <summary>
        /// Blocks the caller until the given <paramref name="actionSetArray"/> completes (based on the chosen <paramref name="completionType"/>) or the <paramref name="spinEarlyExitCodeDelegate"/> returns a non-null string (typically based on a timer expiring, cancel requested, part shutdown requested, ...).
        /// This evaluation takes place in a spin loop with the spin's wait period given using the <paramref name="spinInterval"/> value.
        /// If the caller does not provide a spinInterval then 0.1 seconds will be used.  The any given <paramref name="spinInterval"/> value will be clipped to be between 0.001 seconds and 0.5 seconds
        /// </summary>
        public static string WaitUntilSetComplete <TClientFacetType>(this TClientFacetType[] actionSetArray, Func <string> spinEarlyExitCodeDelegate, TimeSpan?spinInterval = null, WaitForSetCompletionType completionType = WaitForSetCompletionType.All)
            where TClientFacetType : IClientFacet
        {
            TimeSpan useSpinInterval = (spinInterval ?? (0.1).FromSeconds()).Clip(spinIntervalClipRangeMinValue, spinIntervalClipRangeMaxValue);

            spinEarlyExitCodeDelegate = spinEarlyExitCodeDelegate ?? (() => null);

            IClientFacet firstAction = actionSetArray.FirstOrDefault();

            if (firstAction != null)
            {
                for (; ;)
                {
                    IClientFacet firstWaitableAction = null;

                    switch (completionType)
                    {
                    case WaitForSetCompletionType.Any:
                    {
                        var firstCompleteAction = actionSetArray.FirstOrDefault(a => a.ActionState.IsComplete);
                        if (firstCompleteAction != null)
                        {
                            return(firstCompleteAction.ActionState.ResultCode);
                        }

                        firstWaitableAction = actionSetArray.FirstOrDefault(a => !a.ActionState.IsComplete);
                    }
                    break;

                    case WaitForSetCompletionType.All:
                        firstWaitableAction = actionSetArray.FirstOrDefault(a => !a.ActionState.IsComplete);
                        if (firstWaitableAction == null)
                        {
                            var firstFailedAction = actionSetArray.FirstOrDefault(a => a.ActionState.Failed);
                            if (firstFailedAction != null)
                            {
                                return(firstFailedAction.ActionState.ResultCode);
                            }
                            else
                            {
                                return("");
                            }
                        }
                        break;

                    case WaitForSetCompletionType.AllOrAnyFailure:
                    {
                        // NOTE: in the following case the order of evaluation is important as the ActionStates of incomplete actions may change between the evaluation of the firstWaitableAction and of the firstFailedAction
                        firstWaitableAction = actionSetArray.FirstOrDefault(a => !a.ActionState.IsComplete);
                        var firstFailedAction = actionSetArray.FirstOrDefault(a => a.ActionState.Failed);
                        if (firstFailedAction != null)
                        {
                            return(firstFailedAction.ActionState.ResultCode);
                        }
                        else if (firstWaitableAction == null)
                        {
                            return("");
                        }
                    }

                    break;
                    }

                    string earlyExitCode = spinEarlyExitCodeDelegate();
                    if (earlyExitCode != null)
                    {
                        return(earlyExitCode);
                    }

                    if (firstWaitableAction != null)
                    {
                        firstWaitableAction.WaitUntilComplete(useSpinInterval);
                    }
                    else
                    {
                        spinIntervalClipRangeMinValue.Sleep();
                    }
                }
            }

            return("");      // there were no actions to run
        }
Пример #2
0
        /// <summary>
        /// Attempts to Start each of the given <paramref name="actionSetArray"/> of actions and then waits for them to complete.
        /// If some or all of them are started, gets the exitCode that results from passing the corresponding set of parameters to WaitUntilSetComplete for the set of successfully started actions.
        /// Then returns either the non-empty exit code from WaitUntilSetComplete, or the first non-empty failure code from attempting to start the actions, or the empty string to indicate success.
        /// </summary>
        public static string RunSet <TClientFacetType>(this TClientFacetType[] actionSetArray, Func <string> spinEarlyExitCodeDelegate = null, TimeSpan?spinInterval = null, WaitForSetCompletionType completionType = WaitForSetCompletionType.All)
            where TClientFacetType : IClientFacet
        {
            int    successfullyStartedCount = 0;
            string firstStartFailureEC      = null;

            foreach (var a in actionSetArray)
            {
                var ec = a.Start();
                if (ec.IsNullOrEmpty())
                {
                    successfullyStartedCount++;
                }
                else
                {
                    firstStartFailureEC = firstStartFailureEC ?? ec;
                }
            }

            if (successfullyStartedCount > 0)
            {
                string waitResultEC = null;
                if (firstStartFailureEC == null)
                {
                    waitResultEC = actionSetArray.WaitUntilSetComplete(spinEarlyExitCodeDelegate: spinEarlyExitCodeDelegate, spinInterval: spinInterval, completionType: completionType);
                }
                else
                {
                    waitResultEC = actionSetArray.Take(successfullyStartedCount).ToArray().WaitUntilSetComplete(spinEarlyExitCodeDelegate: spinEarlyExitCodeDelegate, spinInterval: spinInterval, completionType: completionType);
                }

                if (!waitResultEC.IsNullOrEmpty())
                {
                    return(waitResultEC);
                }
            }

            return(firstStartFailureEC ?? "");
        }
Пример #3
0
        /// <summary>
        /// Blocks the caller until the given actionSet completes (based on the chosen completionType) or the isWaitLimitReachedDelegate returns true (typically based on a timer expiring).
        /// This evaluation takes place in a spin loop with the spin's wait period given using the spinInterval value.
        /// If the caller does not provide a spinInterval then 0.1 seconds will be used.  The any given spinInterval value will be clipped to be between 0.001 seconds and 0.5 seconds
        /// <para/>supports call chaining
        /// </summary>
        public static TClientFacetType [] WaitUntilSetComplete <TClientFacetType>(this TClientFacetType [] actionSetArray, Func <bool> isWaitLimitReachedDelegate = null, TimeSpan?spinInterval = null, WaitForSetCompletionType completionType = WaitForSetCompletionType.All)
            where TClientFacetType : IClientFacet
        {
            TimeSpan useSpinInterval = (spinInterval ?? (0.1).FromSeconds()).Clip(spinIntervalClipRangeMinValue, spinIntervalClipRangeMaxValue);

            Func <string> spinEarlyExitCodeDelegate = null;

            if (isWaitLimitReachedDelegate != null)
            {
                spinEarlyExitCodeDelegate = () => (isWaitLimitReachedDelegate() ? "" : null);
            }

            actionSetArray.WaitUntilSetComplete(spinEarlyExitCodeDelegate: spinEarlyExitCodeDelegate, spinInterval: spinInterval, completionType: completionType);

            return(actionSetArray);
        }