Mercurial > pub > ImplabNet
changeset 259:7d52dc684bbd v3
PollingComponent: implemented correct stopping
author | cin |
---|---|
date | Fri, 13 Apr 2018 03:57:39 +0300 |
parents | d0876436d95d |
children | 547a2fc0d93e |
files | Implab.Test/Implab.Test.csproj Implab.Test/RunnableComponentTests.cs Implab.Test/UnitTest1.cs Implab/Components/PollingComponent.cs Implab/PromiseExtensions.cs Implab/Safe.cs |
diffstat | 6 files changed, 91 insertions(+), 53 deletions(-) [+] |
line wrap: on
line diff
--- a/Implab.Test/Implab.Test.csproj Fri Apr 13 00:44:57 2018 +0300 +++ b/Implab.Test/Implab.Test.csproj Fri Apr 13 03:57:39 2018 +0300 @@ -1,16 +1,16 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net46</TargetFramework> - <FrameworkPathOverride Condition="'$(TargetFramework)'=='net46' and '$(OSTYPE)'=='linux'">/usr/lib/mono/4.5/</FrameworkPathOverride> + <TargetFramework>netcoreapp2.1</TargetFramework> <IsPackable>false</IsPackable> </PropertyGroup> + <ItemGroup> - <ProjectReference Include="../Implab/Implab.csproj" /> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.6.0-preview-20180109-01" /> <PackageReference Include="xunit" Version="2.3.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" /> + <ProjectReference Include="../Implab/Implab.csproj"/> <DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" /> </ItemGroup>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab.Test/RunnableComponentTests.cs Fri Apr 13 03:57:39 2018 +0300 @@ -0,0 +1,42 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Implab.Components; +using Xunit; + +namespace Implab.Test +{ + class TimeLog : PollingComponent { + public TimeLog() : base(true) { + } + + protected override Task Poll(CancellationToken ct) { + Console.WriteLine("Poll"); + return Task.CompletedTask; + } + } + + public class UnitTest1 + { + [Fact] + public async Task Test1() + { + + using(var tl = new TimeLog()) { + tl.StateChanged += (self, args) => Console.WriteLine("{0}", args.State); + tl.Delay = 1000; + tl.Interval = 500; + + + tl.Start(CancellationToken.None); + await tl.Completion; + + await Task.Delay(2000); + + tl.Stop(CancellationToken.None); + await tl.Completion; + await Task.Delay(3000); + } + } + } +}
--- a/Implab.Test/UnitTest1.cs Fri Apr 13 00:44:57 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -using System; -using System.Diagnostics; -using System.Threading; -using Implab.Diagnostics; -using System.Linq; -using Xunit; - -namespace Implab.Test { - using System.Threading.Tasks; - using static Trace<UnitTest1>; - public class UnitTest1 { - [Fact] - public async Task Test1() { - var listener = new SimpleTraceListener(Console.Out); - listener.TraceOutputOptions |= TraceOptions.ThreadId; - - var source = TraceSource; - source.Switch.Level = SourceLevels.All; - - source.Listeners.Add(listener); - - using (LogicalOperation("Test1")){ - await Task.Yield(); - Log(String.Join(", ", Trace.CorrelationManager.LogicalOperationStack.Cast<object>().Select(x => x.ToString()))); - await AsyncDummy(); - Log(String.Join(", ", Trace.CorrelationManager.LogicalOperationStack.Cast<object>().Select(x => x.ToString()))); - } - } - - async Task AsyncDummy() { - using(LogicalOperation("OuterDummy")) - using(LogicalOperation("InnerDummy")) { - Log(String.Join(", ", Trace.CorrelationManager.LogicalOperationStack.Cast<object>().Select(x => x.ToString()))); - await Task.Delay(1); - Log(String.Join(", ", Trace.CorrelationManager.LogicalOperationStack.Cast<object>().Select(x => x.ToString()))); - } - Log(String.Join(", ", Trace.CorrelationManager.LogicalOperationStack.Cast<object>().Select(x => x.ToString()))); - } - } -}
--- a/Implab/Components/PollingComponent.cs Fri Apr 13 00:44:57 2018 +0300 +++ b/Implab/Components/PollingComponent.cs Fri Apr 13 03:57:39 2018 +0300 @@ -9,6 +9,9 @@ readonly CancellationTokenSource m_cancellation = new CancellationTokenSource(); + Task m_pending; + Task m_poll; + /// <summary> /// Poll interval in milliseconds. /// </summary> @@ -41,20 +44,33 @@ } - //TODO override stop + protected override async Task StopInternalAsync(CancellationToken ct) { + // component in Stopping state, no new polls will be scheduled + m_cancellation.Cancel(); + try { + // await for pending poll + await m_poll; + } catch (OperationCanceledException e) { + // OK + } + } protected abstract Task Poll(CancellationToken ct); void ScheduleNextPoll(int timeout) { lock (SynchronizationObject) { - if (State == ExecutionState.Running) + if (State == ExecutionState.Running) { + m_pending = Safe.CreateTask(m_cancellation.Token); + m_poll = m_pending.Then(() => Poll(m_cancellation.Token)); m_timer.Change(timeout, Timeout.Infinite); + } } } - void OnTimer(object state) { + async void OnTimer(object state) { try { - Poll(m_cancellation.Token); + m_pending.Start(); + await m_poll; } catch (Exception e) { UnhandledException.DispatchEvent(this, new UnhandledExceptionEventArgs(e, false)); if (FailOnError)
--- a/Implab/PromiseExtensions.cs Fri Apr 13 00:44:57 2018 +0300 +++ b/Implab/PromiseExtensions.cs Fri Apr 13 03:57:39 2018 +0300 @@ -211,6 +211,15 @@ })); } + public static PromiseAwaiter GetAwaiter(this IPromise that) { + Safe.ArgumentNotNull(that, nameof(that)); + return new PromiseAwaiter(that); + } + + public static PromiseAwaiter<T> GetAwaiter<T>(this IPromise<T> that) { + Safe.ArgumentNotNull(that, nameof(that)); + return new PromiseAwaiter<T>(that); + } } }
--- a/Implab/Safe.cs Fri Apr 13 00:44:57 2018 +0300 +++ b/Implab/Safe.cs Fri Apr 13 03:57:39 2018 +0300 @@ -7,6 +7,7 @@ using System.Collections; using System.Runtime.CompilerServices; using System.Threading.Tasks; +using System.Threading; #if NET_4_5 using System.Threading.Tasks; @@ -151,6 +152,21 @@ public static void NoWait<T>(Task<T> promise) { } + public static void Noop() { + } + + public static void Noop(CancellationToken ct) { + ct.ThrowIfCancellationRequested(); + } + + public static Task CreateTask() { + return new Task(Noop); + } + + public static Task CreateTask(CancellationToken ct) { + return new Task(Noop, ct); + } + [DebuggerStepThrough] public static IPromise<T> Run<T>(Func<IPromise<T>> action) { ArgumentNotNull(action, "action"); @@ -162,10 +178,5 @@ } } -#if NET_4_5 - public static void NoWait(Task t) { - } -#endif - } }