Esempio n. 1
0
        public static async Task <T> TryWithExponentialBackoff <T>(Func <Task <T> > taskToTry,
                                                                   Action <Exception> onError = null, int maxNrOfRetries = -1, int maxDelayInMs = -1, int initialExponent = 0)
        {
            int       retryCount = initialExponent;
            Stopwatch timer      = Stopwatch.StartNew();

            do
            {
                timer.Restart();
                try {
                    Task <T> task   = taskToTry();
                    var      result = await task;
                    if (!task.IsFaulted && !task.IsFaulted)
                    {
                        return(result);
                    }
                } catch (Exception e) { onError.InvokeIfNotNull(e); }
                retryCount++;
                int delay = (int)(Math.Pow(2, retryCount) - timer.ElapsedMilliseconds);
                if (delay > maxDelayInMs && maxDelayInMs > 0)
                {
                    delay = maxDelayInMs;
                }
                if (delay > 0)
                {
                    await TaskV2.Delay(delay);
                }
                if (retryCount >= maxNrOfRetries && maxNrOfRetries > 0)
                {
                    throw new OperationCanceledException("No success after " + retryCount + " retries");
                }
            } while (true);
        }
Esempio n. 2
0
 private async Task MonitorProgress(IProgress targetProgressToUpdate, int updateIntervalInMs)
 {
     do
     {
         targetProgressToUpdate.SetCount(ElapsedMilliseconds, timerDurationInMs);
         await TaskV2.Delay(updateIntervalInMs);
     } while (!timerTask.IsCompleted);
     targetProgressToUpdate.SetComplete();
 }
Esempio n. 3
0
        public static async Task WithTimeout(this Task self, int timeoutInMs)
        {
            var completedTask = await Task.WhenAny(self, TaskV2.Delay(timeoutInMs));

            if (completedTask != self)
            {
                throw new TimeoutException();
            }
            await self;  // use await to propagate exceptions
        }
Esempio n. 4
0
        /// <summary>
        /// This will create an EventHandler where the first call is executed and the last call is executed but
        /// every call in between that is below the passed millisecond threshold is ignored
        /// </summary>
        public static EventHandler <T> AsThrottledDebounce <T>(this EventHandler <T> self, double delayInMs, bool skipFirstEvent = false)
        {
            object    threadLock = new object();
            T         latestEventArgs;
            Stopwatch s = Stopwatch.StartNew();
            bool      triggerFirstEvent = !skipFirstEvent;
            Func <object, T, Task> asyncEventHandler = async(sender, eventArgs) => {
                lock (threadLock) {
                    latestEventArgs = eventArgs;
                    s.Restart();
                    if (triggerFirstEvent)
                    {
                        triggerFirstEvent = false;
                        self(sender, eventArgs);
                    }
                }
                var delay = TaskV2.Delay((int)(delayInMs * 1.1f));
                await HandlerTaskResultIfNeeded(eventArgs);

                await delay;
                if (s.ElapsedMilliseconds >= delayInMs)
                {
                    lock (threadLock) {
                        if (s.ElapsedMilliseconds >= delayInMs)
                        {
                            s.Reset(); // Stop (and reset) and only continue below
                            self(sender, latestEventArgs);
                            if (!skipFirstEvent)
                            {
                                triggerFirstEvent = true;
                            }
                        }
                    }
                    await HandlerTaskResultIfNeeded(latestEventArgs);

                    s.Restart();
                }
            };

            return((sender, eventArgs) => {
                asyncEventHandler(sender, eventArgs).ContinueWithSameContext(finishedTask => {
                    // A failed task cant be awaited but it can be logged
                    if (finishedTask.Exception != null)
                    {
                        Log.e(finishedTask.Exception);
                    }
                });
            });
        }
Esempio n. 5
0
        private async Task NewTimerTask(int timerDurationInMs)
        {
            this.timerDurationInMs = timerDurationInMs;
            cancellationToken      = new CancellationTokenSource();
            timer = StopwatchV2.StartNewV2();
            await TaskV2.Delay(timerDurationInMs, cancellationToken.Token);

            int durationSoFar = (int)timer.ElapsedMilliseconds;

            if (durationSoFar < timerDurationInMs)
            {
                await TaskV2.Delay(timerDurationInMs - durationSoFar);
            }
            Stop();
        }
Esempio n. 6
0
        public static async Task RunRepeated(Func <Task <bool> > task, int delayInMsBetweenIterations, CancellationToken cancelToken, int delayInMsBeforeFirstExecution = 0, float repetitions = -1)
        {
            if (delayInMsBeforeFirstExecution > 0)
            {
                await Delay(delayInMsBeforeFirstExecution);
            }
            while (repetitions != 0)
            {
                cancelToken.ThrowIfCancellationRequested();
                if (!await task())
                {
                    break;
                }
                await TaskV2.Delay(delayInMsBetweenIterations);

                repetitions--;
            }
        }
Esempio n. 7
0
        public static async Task MonitorPositionForProgress(this Stream self, Action <long> onProgress, CancellationTokenSource cancel, int delayInMsBetweenProgress = 10)
        {
            onProgress.ThrowErrorIfNull("onProgress");
            long progress = 0;

            do
            {
                cancel?.Token.ThrowIfCancellationRequested();
                await TaskV2.Delay(delayInMsBetweenProgress);

                long newProgress = 100l * self.Position / self.Length;
                if (progress != newProgress)
                {
                    onProgress(newProgress);
                }
                progress = newProgress;
            } while (progress < 100);
        }
Esempio n. 8
0
        public async Task WhenAllTasksCompleted(int millisecondsDelay = 50, bool flushQueueAfterCompletion = false)
        {
            await Task.WhenAll(Tasks);

            if (millisecondsDelay > 0)
            {
                await TaskV2.Delay(millisecondsDelay);
            }
            // If there were new tasks added in the meantime, do another wait for the remaining tasks:
            if (!IsAllTasksCompleted())
            {
                await WhenAllTasksCompleted();
            }
            if (flushQueueAfterCompletion)
            {
                Tasks.Clear();
            }                                                 // Automatically flush task queue after all are done?
        }
Esempio n. 9
0
        /// <summary>
        /// This will create an EventHandler where the first call is executed and the last call is executed but
        /// every call in between that is below the passed millisecond threshold is ignored
        /// </summary>
        /// <param name="skipFirstEvent"> if set to true there will be no instant execution of the very first call to the debounced async func </param>
        public static EventHandler <T> AsThrottledDebounce <T>(this EventHandler <T> self, double delayInMs, bool skipFirstEvent = false)
        {
            int triggerFirstEvent = skipFirstEvent ? 0 : 1;
            int last = 0;

            return((sender, eventArgs) => {
                var current = Interlocked.Increment(ref last);
                if (!skipFirstEvent && ThreadSafety.FlipToFalse(ref triggerFirstEvent))
                {
                    self(sender, eventArgs);
                }
                else
                {
                    TaskV2.Delay((int)delayInMs).ContinueWithSameContext(task => {
                        if (current == last)
                        {
                            self(sender, eventArgs);
                        }
                    });
                }
            });
        }