/// <inheritdoc /> public IAsyncLoop CreateAndRunAsyncLoop <T>(string name, Func <CancellationToken, Task> loop, CancellationToken cancellation, TimeSpan?repeatEvery = null, TimeSpan?startAfter = null) { Guard.NotEmpty(name, nameof(name)); Guard.NotNull(loop, nameof(loop)); Guard.NotNull(cancellation, nameof(cancellation)); // instantiate the loop IAsyncLoop loopInstance = new AsyncLoop(name, this.logger, loop); Task loopTask; lock (this.lockAsyncLoops) { this.asyncLoops.Add(loopInstance, new AsyncTaskInfo(name)); } loopTask = loopInstance.Run(cancellation, repeatEvery ?? TimeSpan.FromMilliseconds(DefaultLoopRepeatInterval), startAfter).RunningTask; // task will continue with onAsyncDelegateUnhandledException if @delegate had unhandled exceptions loopTask.ContinueWith(this.onAsyncLoopUnhandledException, loopInstance, TaskContinuationOptions.OnlyOnFaulted); // task will continue with onAsyncDelegateCompleted if @delegate completed or was canceled loopTask.ContinueWith(this.onAsyncLoopCompleted, loopInstance, TaskContinuationOptions.NotOnFaulted); return(loopInstance); }
/// <summary> /// Notifies about blocks, starting from block with hash passed as parameter. /// </summary> /// <param name="startHash">The hash of the block from which to start notifying</param> /// <param name="cancellationToken">A cancellation token</param> public virtual void Notify(uint256 startHash, CancellationToken cancellationToken) { // sets the location of the puller to the latest hash that was broadcasted this.Puller.SetLocation(this.Chain.GetBlock(startHash)); AsyncLoop.Run("block notifier", token => { // send notifications for all the following blocks while (true) { var block = this.Puller.NextBlock(token); if (block != null) { this.signals.Blocks.Broadcast(block); } else { break; } } return(Task.CompletedTask); }, cancellationToken); }
public void RelayWorker(CancellationToken cancellationToken) { AsyncLoop.Run("BlockStore.RelayWorker", async token => { var blocks = this.blockHashesToAnnounce.Keys.ToList(); if (!blocks.Any()) { return; } uint256 outer; foreach (var blockHash in blocks) { this.blockHashesToAnnounce.TryRemove(blockHash, out outer); } var nodes = this.connection.ConnectedNodes; if (!nodes.Any()) { return; } // announce the blocks on each nodes behaviour var behaviours = nodes.Select(s => s.Behavior <BlockStoreBehavior>()); foreach (var behaviour in behaviours) { await behaviour.AnnounceBlocks(blocks).ConfigureAwait(false); } }, cancellationToken, repeatEvery: TimeSpans.Second, startAfter: TimeSpans.FiveSeconds); }
public async Task RunLogsStartAndStopAsync() { var asyncLoop = new AsyncLoop("TestLoop", this.FullNodeLogger.Object, async token => { await this.DoTask(token); }); await asyncLoop.Run(new CancellationTokenSource(1000).Token, TimeSpan.FromMilliseconds(330)).RunningTask; }
public async Task RunWithoutDelayRunsTaskUntilCancelled() { var asyncLoop = new AsyncLoop("TestLoop", async token => { await DoTask(token); }); await asyncLoop.Run(new CancellationTokenSource(90).Token, TimeSpan.FromMilliseconds(33)); Assert.Equal(3, this.iterationCount); }
public async Task RunWithDelayRunsTaskUntilCancelledAsync() { var asyncLoop = new AsyncLoop("TestLoop", NullLogger.Instance, async token => { await this.DoTask(token); }); await asyncLoop.Run(new CancellationTokenSource(1000).Token, TimeSpan.FromMilliseconds(300), TimeSpan.FromMilliseconds(100)).RunningTask; Assert.True(this.iterationCount > 1); }
public void RunWithDelayRunsTaskUntilCancelled() { var asyncLoop = new AsyncLoop("TestLoop", async token => { await DoTask(token); }); asyncLoop.Run(new CancellationTokenSource(100).Token, TimeSpan.FromMilliseconds(33), TimeSpan.FromMilliseconds(40)).Wait(); Assert.Equal(2, iterationCount); }
public async Task RunWithoutDelayRunsTaskUntilCancelledAsync() { var asyncLoop = new AsyncLoop("TestLoop", NullLogger.Instance, async token => { this.iterationCount++; await Task.CompletedTask; }); await asyncLoop.Run(new CancellationTokenSource(900).Token, TimeSpan.FromMilliseconds(330)).RunningTask; Assert.True(this.iterationCount > 1); }
public async Task RunWithCancellationTokenRunsUntilExceptionOccursAsync() { var asyncLoop = new AsyncLoop("TestLoop", this.FullNodeLogger.Object, async token => { await this.DoExceptionalTask(token); }); await asyncLoop.Run(new CancellationTokenSource(1500).Token, TimeSpan.FromMilliseconds(330)).RunningTask; this.AssertLog <InvalidOperationException>(this.FullNodeLogger, LogLevel.Critical, "Cannot run more than 3 times.", "TestLoop threw an unhandled exception"); Assert.Equal(3, this.iterationCount); }
public async Task RunLogsStartAndStop() { var asyncLoop = new AsyncLoop("TestLoop", this.FullNodeLogger.Object, async token => { await this.DoTask(token); }); await asyncLoop.Run(new CancellationTokenSource(1000).Token, TimeSpan.FromMilliseconds(330)).RunningTask; this.AssertLog(this.FullNodeLogger, LogLevel.Information, "TestLoop starting"); this.AssertLog(this.FullNodeLogger, LogLevel.Information, "TestLoop stopping"); }
public void RunLogsStartAndStop() { var asyncLoop = new AsyncLoop("TestLoop", async token => { await DoTask(token); }); asyncLoop.Run(new CancellationTokenSource(100).Token, TimeSpan.FromMilliseconds(33)).Wait(); AssertLog(FullNodeLogger, LogLevel.Information, "TestLoop starting"); AssertLog(FullNodeLogger, LogLevel.Information, "TestLoop stopping"); }
public async Task RunOperationCanceledExceptionThrownBeforeCancellationTokenIsCancelledLogsExceptionAsync() { var asyncLoop = new AsyncLoop("TestLoop", this.FullNodeLogger.Object, async token => { await this.DoOperationCanceledExceptionTask(token); }); await asyncLoop.Run(new CancellationTokenSource(800).Token, TimeSpan.FromMilliseconds(300)).RunningTask; this.AssertLog <OperationCanceledException>(this.FullNodeLogger, LogLevel.Critical, "This should not block the task from continuing.", "TestLoop threw an unhandled exception"); Assert.Equal(1, this.iterationCount); }
public void Loop(CancellationToken cancellationToken) { // A loop that writes pending blocks to store // or downloads missing blocks then writing to store AsyncLoop.Run("BlockStoreLoop.DownloadBlocks", async token => { await DownloadAndStoreBlocks(cancellationToken); }, cancellationToken, repeatEvery: TimeSpans.Second, startAfter: TimeSpans.FiveSeconds); }
public void RunWithCancellationTokenRunsUntilExceptionOccurs() { var asyncLoop = new AsyncLoop("TestLoop", async token => { await DoExceptionalTask(token); }); asyncLoop.Run(new CancellationTokenSource(150).Token, TimeSpan.FromMilliseconds(33)).Wait(); AssertLog(FullNodeLogger, LogLevel.Information, "TestLoop starting"); AssertLog(FullNodeLogger, LogLevel.Information, "TestLoop stopping"); AssertLog <InvalidOperationException>(FullNodeLogger, LogLevel.Critical, "Cannot run more than 3 times.", "TestLoop threw an unhandled exception"); Assert.Equal(3, iterationCount); }
public async Task RunWithoutCancellationTokenRunsUntilExceptionOccurs() { var asyncLoop = new AsyncLoop("TestLoop", this.FullNodeLogger.Object, async token => { await this.DoExceptionalTask(token); }); await asyncLoop.Run(TimeSpan.FromMilliseconds(330)); this.AssertLog(this.FullNodeLogger, LogLevel.Information, "TestLoop starting"); this.AssertLog(this.FullNodeLogger, LogLevel.Information, "TestLoop stopping"); this.AssertLog <InvalidOperationException>(this.FullNodeLogger, LogLevel.Critical, "Cannot run more than 3 times.", "TestLoop threw an unhandled exception"); Assert.Equal(3, this.iterationCount); }
public void RunOperationCanceledExceptionThrownBeforeCancellationTokenIsCancelledLogsException() { var asyncLoop = new AsyncLoop("TestLoop", async token => { await DoOperationCanceledExceptionTask(token); }); asyncLoop.Run(new CancellationTokenSource(80).Token, TimeSpan.FromMilliseconds(33)).Wait(); AssertLog(FullNodeLogger, LogLevel.Information, "TestLoop starting"); AssertLog(FullNodeLogger, LogLevel.Information, "TestLoop stopping"); AssertLog <OperationCanceledException>(FullNodeLogger, LogLevel.Critical, "This should not block the task from continuing.", "TestLoop threw an unhandled exception"); Assert.Equal(1, iterationCount); }
public Task Mine(List <TrxStakingInfo> stakeTxes) { if (this.mining != null) { return(this.mining); // already mining } this.mining = AsyncLoop.Run("PosMining.Mine", token => { this.GenerateBlocks(stakeTxes); return(Task.CompletedTask); }, cancellationProvider.Cancellation.Token, repeatEvery: TimeSpan.FromMilliseconds(this.minerSleep), startAfter: TimeSpans.TenSeconds); return(this.mining); }
/// <inheritdoc /> public Task WaitForChainDownloadAsync() { // make sure the chain is downloaded CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); return(AsyncLoop.Run("WalletFeature.DownloadChain", token => { // wait until the chain is downloaded. We wait until a block is from an hour ago. if (this.chain.IsDownloaded()) { cancellationTokenSource.Cancel(); } return Task.CompletedTask; }, cancellationTokenSource.Token, repeatEvery: TimeSpans.FiveSeconds)); }
public Task Mine(Script reserveScript) { if (this.mining != null) { return(this.mining); // already mining } this.mining = AsyncLoop.Run("PowMining.Mine", token => { this.GenerateBlocks(new ReserveScript { reserveSfullNodecript = reserveScript }, int.MaxValue, int.MaxValue); this.mining = null; return(Task.CompletedTask); }, cancellationProvider.Cancellation.Token, repeatEvery: TimeSpans.RunOnce, startAfter: TimeSpans.TenSeconds); return(this.mining); }
/// <summary> /// Notifies about blocks, starting from block with hash passed as parameter. /// </summary> /// <param name="cancellationToken">A cancellation token</param> public virtual void Notify(CancellationToken cancellationToken) { AsyncLoop.Run("block notifier", token => { // if the StartHash hasn't been set yet if (this.StartHash == null) { return(Task.CompletedTask); } // make sure the chain has been downloaded ChainedBlock startBlock = this.Chain.GetBlock(this.StartHash); if (startBlock == null) { return(Task.CompletedTask); } // sets the location of the puller to the latest hash that was broadcasted this.Puller.SetLocation(startBlock); // send notifications for all the following blocks while (!this.reSync) { var block = this.Puller.NextBlock(token); if (block != null) { // broadcast the block to the registered observers this.signals.Blocks.Broadcast(block); } else { break; } } this.reSync = false; return(Task.CompletedTask); }, cancellationToken); }
public void Stake_StakingLoopThrowsConsensusErrorException_AddsErrorToRpcStakingInfoModel() { var asyncLoop = new AsyncLoop("PosMining.Stake2", this.FullNodeLogger.Object, token => { return(Task.CompletedTask); }); this.asyncProvider.Setup(a => a.CreateAndRunAsyncLoop("PosMining.Stake", It.IsAny <Func <CancellationToken, Task> >(), It.IsAny <CancellationToken>(), It.Is <TimeSpan>(t => t.Milliseconds == 500), TimeSpans.Second)) .Callback <string, Func <CancellationToken, Task>, CancellationToken, TimeSpan?, TimeSpan?>((name, func, token, repeat, start) => { func(token); }) .Returns(asyncLoop) .Verifiable(); bool isSystemTimeOutOfSyncCalled = false; this.timeSyncBehaviorState.Setup(c => c.IsSystemTimeOutOfSync) .Returns(() => { if (!isSystemTimeOutOfSyncCalled) { isSystemTimeOutOfSyncCalled = true; throw new ConsensusErrorException(new ConsensusError("15", "Consensus error.")); } this.cancellationTokenSource.Cancel(); throw new InvalidOperationException("End the loop"); }); this.posMinting.Stake(new List <WalletSecret>() { new WalletSecret() { WalletName = "wallet1", WalletPassword = "******" } }); asyncLoop.Run(); GetStakingInfoModel model = this.posMinting.GetGetStakingInfoModel(); Assert.Equal("Consensus error.", model.Errors); }
private void RelayWorker(CancellationToken cancellationToken) { AsyncLoop.Run("MemoryPool.RelayWorker", async token => { var nodes = this.connection.ConnectedNodes; if (!nodes.Any()) { return; } // announce the blocks on each nodes behaviour var behaviours = nodes.Select(s => s.Behavior <MempoolBehavior>()); foreach (var behaviour in behaviours) { await behaviour.SendTrickle().ConfigureAwait(false); } }, cancellationToken, repeatEvery: TimeSpans.TenSeconds, startAfter: TimeSpans.TenSeconds); }
public async Task AsyncLoopRepeatEveryIntervalCanBeChangedWhileRunningAsync() { int iterations = 0; IAsyncLoop asyncLoop = new AsyncLoop("TestLoop", NullLogger.Instance, async token => { iterations++; }); Task loopRun = asyncLoop.Run(new CancellationTokenSource(1000).Token, TimeSpan.FromMilliseconds(300)).RunningTask; await Task.Delay(500); asyncLoop.RepeatEvery = TimeSpan.FromMilliseconds(100); // At this point there were 2 iterations, 600 ms passed. await loopRun; // Should be 6 but in some slow environments occasionally can be 5. Assert.True(iterations >= 5); }
public async Task AsyncLoopRepeatEveryIntervalCanBeChangedWhileRunningAsync() { int iterations = 0; IAsyncLoop asyncLoop = null; asyncLoop = new AsyncLoop("TestLoop", NullLogger.Instance, token => { iterations++; if (iterations == 2) { asyncLoop.RepeatEvery = TimeSpan.FromMilliseconds(200); } return(Task.CompletedTask); }); Task loopRun = asyncLoop.Run(new CancellationTokenSource(5000).Token, TimeSpan.FromMilliseconds(1000)).RunningTask; await loopRun; Assert.True(iterations >= 6); }