Beispiel #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);
        }
        /// <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   currentlyThrottling = false;
            bool   needsFinalCall      = false;
            object threadLock          = new object();
            Func <object, T, Task> asyncEventHandler = async(sender, eventArgs) => {
                lock (threadLock) {
                    if (currentlyThrottling)
                    {
                        needsFinalCall = true; return;
                    }
                    currentlyThrottling = true;
                    self(sender, eventArgs);
                }
                await TaskV2.Delay(TimeSpan.FromMilliseconds(delayInMs));

                lock (threadLock) {
                    if (needsFinalCall)
                    {
                        try { self(sender, eventArgs); } catch (Exception e) { Log.e(e); }
                    }
                    currentlyThrottling = false;
                    needsFinalCall      = false;
                }
            };

            return((sender, eventArgs) => { asyncEventHandler(sender, eventArgs); });
        }
Beispiel #3
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, latestEventArgs);
                    }
                }
                await TaskV2.Delay(TimeSpan.FromMilliseconds(delayInMs * 1.1f));

                lock (threadLock) {
                    if (s.ElapsedMilliseconds >= delayInMs)
                    {
                        s.Restart();
                        self(sender, latestEventArgs);
                        if (!skipFirstEvent)
                        {
                            triggerFirstEvent = true;
                        }
                    }
                }
            };

            return((sender, eventArgs) => { asyncEventHandler(sender, eventArgs); });
        }
Beispiel #4
0
        /// <summary>
        /// This will create an async func 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>
        /// <exception cref="TaskCanceledException"> If the func was canceled because another one after it replaced it the returned Task will indicate this </exception>
        public static Func <T, Task> AsThrottledDebounce <T>(this Func <T, Task> self, double delayInMs, bool skipFirstEvent = false)
        {
            int triggerFirstEvent = skipFirstEvent ? 0 : 1;
            int last = 0;

            return(async(t) => {
                var current = Interlocked.Increment(ref last);
                if (!skipFirstEvent && ThreadSafety.FlipToFalse(ref triggerFirstEvent))
                {
                    await self(t);
                }
                else
                {
                    await TaskV2.Delay((int)delayInMs);

                    if (current == last)
                    {
                        await self(t);
                    }
                    else
                    {
                        throw new TaskCanceledException();
                    }
                }
            });
        }
 private async Task RunInternetCheckLoop(Task firstInetCheck)
 {
     await firstInetCheck;
     await TaskV2.RunRepeated(async() => {
         HasInetAsync = RunInternetCheck();
         await HasInetAsync;
         return(true);
     }, delayInMsBetweenIterations : 3000, cancelToken : cancelToken.Token);
 }
        public InternetStateManager()
        {
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
            TaskV2.RunRepeated(async() => {
                await HasInet(await RestFactory.instance.HasInternet());
                return(true);
            }, delayInMsBetweenIterations: 3000, cancelToken: cancelToken.Token);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
        }
Beispiel #7
0
 private async Task MonitorProgress(IProgress targetProgressToUpdate, int updateIntervalInMs)
 {
     do
     {
         targetProgressToUpdate.SetCount(ElapsedMilliseconds, timerDurationInMs);
         await TaskV2.Delay(updateIntervalInMs);
     } while (!timerTask.IsCompleted);
     targetProgressToUpdate.SetComplete();
 }
Beispiel #8
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
        }
        public Task Run(Func <CancellationToken, Task> asyncAction, CancellationTokenSource cancellationTokenSource)
        {
            if (!ReferenceEquals(Cancel, cancellationTokenSource))
            {
                cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationTokenSource.Token, Cancel.Token);
            }
            var t = TaskV2.Run(async() => {
                ThrowIfCancellationRequested(cancellationTokenSource);
                await asyncAction(cancellationTokenSource.Token);
                ThrowIfCancellationRequested(cancellationTokenSource);
            }, cancellationTokenSource, Scheduler);

            return(AddToManagedTasks(t));
        }
Beispiel #10
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);
                    }
                });
            });
        }
Beispiel #11
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();
        }
        public async Task <T> Run <T>(Func <CancellationToken, Task <T> > asyncFunction, CancellationTokenSource cancellationTokenSource)
        {
            if (!ReferenceEquals(Cancel, cancellationTokenSource))
            {
                cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationTokenSource.Token, Cancel.Token);
            }
            Task <T> t = TaskV2.Run(async() => {
                ThrowIfCancellationRequested(cancellationTokenSource);
                T result = await asyncFunction(cancellationTokenSource.Token);
                ThrowIfCancellationRequested(cancellationTokenSource);
                return(result);
            }, cancellationTokenSource, Scheduler);

            await AddToManagedTasks(t);

            return(await t);
        }
Beispiel #13
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--;
            }
        }
Beispiel #14
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);
        }
        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?
        }
Beispiel #16
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);
                        }
                    });
                }
            });
        }