##// END OF EJS Templates
PollingComponent: implemented correct stopping
cin -
r259:7d52dc684bbd v3
parent child
Show More
@@ -0,0 +1,42
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 using Implab.Components;
5 using Xunit;
6
7 namespace Implab.Test
8 {
9 class TimeLog : PollingComponent {
10 public TimeLog() : base(true) {
11 }
12
13 protected override Task Poll(CancellationToken ct) {
14 Console.WriteLine("Poll");
15 return Task.CompletedTask;
16 }
17 }
18
19 public class UnitTest1
20 {
21 [Fact]
22 public async Task Test1()
23 {
24
25 using(var tl = new TimeLog()) {
26 tl.StateChanged += (self, args) => Console.WriteLine("{0}", args.State);
27 tl.Delay = 1000;
28 tl.Interval = 500;
29
30
31 tl.Start(CancellationToken.None);
32 await tl.Completion;
33
34 await Task.Delay(2000);
35
36 tl.Stop(CancellationToken.None);
37 await tl.Completion;
38 await Task.Delay(3000);
39 }
40 }
41 }
42 }
@@ -1,16 +1,16
1 <Project Sdk="Microsoft.NET.Sdk">
1 <Project Sdk="Microsoft.NET.Sdk">
2
2
3 <PropertyGroup>
3 <PropertyGroup>
4 <TargetFramework>net46</TargetFramework>
4 <TargetFramework>netcoreapp2.1</TargetFramework>
5 <FrameworkPathOverride Condition="'$(TargetFramework)'=='net46' and '$(OSTYPE)'=='linux'">/usr/lib/mono/4.5/</FrameworkPathOverride>
6
5
7 <IsPackable>false</IsPackable>
6 <IsPackable>false</IsPackable>
8 </PropertyGroup>
7 </PropertyGroup>
8
9 <ItemGroup>
9 <ItemGroup>
10 <ProjectReference Include="../Implab/Implab.csproj" />
10 <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.6.0-preview-20180109-01" />
11 <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
12 <PackageReference Include="xunit" Version="2.3.1" />
11 <PackageReference Include="xunit" Version="2.3.1" />
13 <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
12 <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
13 <ProjectReference Include="../Implab/Implab.csproj"/>
14 <DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
14 <DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
15 </ItemGroup>
15 </ItemGroup>
16
16
@@ -9,6 +9,9 namespace Implab.Components {
9
9
10 readonly CancellationTokenSource m_cancellation = new CancellationTokenSource();
10 readonly CancellationTokenSource m_cancellation = new CancellationTokenSource();
11
11
12 Task m_pending;
13 Task m_poll;
14
12 /// <summary>
15 /// <summary>
13 /// Poll interval in milliseconds.
16 /// Poll interval in milliseconds.
14 /// </summary>
17 /// </summary>
@@ -41,20 +44,33 namespace Implab.Components {
41 }
44 }
42
45
43
46
44 //TODO override stop
47 protected override async Task StopInternalAsync(CancellationToken ct) {
48 // component in Stopping state, no new polls will be scheduled
49 m_cancellation.Cancel();
50 try {
51 // await for pending poll
52 await m_poll;
53 } catch (OperationCanceledException e) {
54 // OK
55 }
56 }
45
57
46 protected abstract Task Poll(CancellationToken ct);
58 protected abstract Task Poll(CancellationToken ct);
47
59
48 void ScheduleNextPoll(int timeout) {
60 void ScheduleNextPoll(int timeout) {
49 lock (SynchronizationObject) {
61 lock (SynchronizationObject) {
50 if (State == ExecutionState.Running)
62 if (State == ExecutionState.Running) {
63 m_pending = Safe.CreateTask(m_cancellation.Token);
64 m_poll = m_pending.Then(() => Poll(m_cancellation.Token));
51 m_timer.Change(timeout, Timeout.Infinite);
65 m_timer.Change(timeout, Timeout.Infinite);
66 }
52 }
67 }
53 }
68 }
54
69
55 void OnTimer(object state) {
70 async void OnTimer(object state) {
56 try {
71 try {
57 Poll(m_cancellation.Token);
72 m_pending.Start();
73 await m_poll;
58 } catch (Exception e) {
74 } catch (Exception e) {
59 UnhandledException.DispatchEvent(this, new UnhandledExceptionEventArgs(e, false));
75 UnhandledException.DispatchEvent(this, new UnhandledExceptionEventArgs(e, false));
60 if (FailOnError)
76 if (FailOnError)
@@ -211,6 +211,15 namespace Implab {
211 }));
211 }));
212 }
212 }
213
213
214 public static PromiseAwaiter GetAwaiter(this IPromise that) {
215 Safe.ArgumentNotNull(that, nameof(that));
216 return new PromiseAwaiter(that);
217 }
218
219 public static PromiseAwaiter<T> GetAwaiter<T>(this IPromise<T> that) {
220 Safe.ArgumentNotNull(that, nameof(that));
221 return new PromiseAwaiter<T>(that);
222 }
214
223
215 }
224 }
216 }
225 }
@@ -7,6 +7,7 using System.Diagnostics;
7 using System.Collections;
7 using System.Collections;
8 using System.Runtime.CompilerServices;
8 using System.Runtime.CompilerServices;
9 using System.Threading.Tasks;
9 using System.Threading.Tasks;
10 using System.Threading;
10
11
11 #if NET_4_5
12 #if NET_4_5
12 using System.Threading.Tasks;
13 using System.Threading.Tasks;
@@ -151,6 +152,21 namespace Implab
151 public static void NoWait<T>(Task<T> promise) {
152 public static void NoWait<T>(Task<T> promise) {
152 }
153 }
153
154
155 public static void Noop() {
156 }
157
158 public static void Noop(CancellationToken ct) {
159 ct.ThrowIfCancellationRequested();
160 }
161
162 public static Task CreateTask() {
163 return new Task(Noop);
164 }
165
166 public static Task CreateTask(CancellationToken ct) {
167 return new Task(Noop, ct);
168 }
169
154 [DebuggerStepThrough]
170 [DebuggerStepThrough]
155 public static IPromise<T> Run<T>(Func<IPromise<T>> action) {
171 public static IPromise<T> Run<T>(Func<IPromise<T>> action) {
156 ArgumentNotNull(action, "action");
172 ArgumentNotNull(action, "action");
@@ -162,10 +178,5 namespace Implab
162 }
178 }
163 }
179 }
164
180
165 #if NET_4_5
166 public static void NoWait(Task t) {
167 }
168 #endif
169
170 }
181 }
171 }
182 }
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

ok, latest stable version should be in default

You need to be logged in to leave comments. Login now