Auto status change to "Under Review"
@@ -12,7 +12,7 namespace Implab.Components { | |||
|
12 | 12 | /// This class provides a basic lifecycle from the creation to the |
|
13 | 13 | /// termination of the component. |
|
14 | 14 | /// </remarks> |
|
15 | public class RunnableComponent : IAsyncComponent, IRunnable, IInitializable, IDisposable { | |
|
15 | public abstract class RunnableComponent : IAsyncComponent, IRunnable, IInitializable, IDisposable { | |
|
16 | 16 | |
|
17 | 17 | /// <summary> |
|
18 | 18 | /// This class bounds <see cref="CancellationTokenSource"/> lifetime to the task, |
@@ -93,6 +93,15 namespace Implab.Components { | |||
|
93 | 93 | |
|
94 | 94 | ExecutionState m_state; |
|
95 | 95 | |
|
96 | /// <summary> | |
|
97 | /// ΠΠ±ΡΠ΅ΠΊΡ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π΄Π»Ρ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠ΅Π½ΠΈΡ ΡΠΎΠ²ΠΌΠ΅ΡΡΠ½ΠΎΠ³ΠΎ Π΄ΠΎΡΡΡΠΏΠ° | |
|
98 | /// ΠΊΠ»ΠΈΠ΅Π½ΡΠ° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ ΠΈ ΠΏΡΠΎΡΠ΅ΡΡΠΎΠ², ΠΏΡΠΎΡΠ΅ΠΊΠ°ΡΡΠΈΡ Π²Π½ΡΡΡΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ, ΠΊ ΠΎΠ±ΡΠ΅ΠΌΡ | |
|
99 | /// ΡΠΎΡΡΠΎΡΠ½ΠΈΡ, Ρ.Π΅.true ΡΠ°ΠΊΠΈΠΌ ΡΠ²ΠΎΠΉΡΡΠ²Π°ΠΌ, ΠΊΠ°ΠΊ <see cref="State"/>, | |
|
100 | /// <see cref="LastError"/>. ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ ΡΠΎΠ±ΡΡΠΈΡ <see cref="StateChanged"/> | |
|
101 | /// Π²ΡΠ·ΡΠ²Π°ΡΡΡΡ ΡΠΆΠ΅ Ρ ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½Π½ΠΎΠΉ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΎΠΉ, ΠΏΠΎΡΡΠΎΠΌΡ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½Π°Ρ | |
|
102 | /// ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΡ Π½Π΅ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ. | |
|
103 | /// </summary> | |
|
104 | public object SynchronizationObject { get { return m_lock; } } | |
|
96 | 105 | |
|
97 | 106 | protected RunnableComponent(bool initialized) { |
|
98 | 107 | State = initialized ? ExecutionState.Ready : ExecutionState.Created; |
@@ -117,6 +126,11 namespace Implab.Components { | |||
|
117 | 126 | |
|
118 | 127 | public Exception LastError { get; private set; } |
|
119 | 128 | |
|
129 | /// <summary> | |
|
130 | /// Π‘ΠΎΠ±ΡΡΠΈΠ΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ.see ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΡΠΎΠ±ΡΡΠΈΡ | |
|
131 | /// Π²ΡΠ·ΡΠ²Π°ΡΡΡΡ Π²Π½ΡΡΡΠΈ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ <see cref="SynchronizationObject"/> ΠΈ Π΄ΠΎΠ»ΠΆΠ½Ρ | |
|
132 | /// Π²ΡΠΏΠΎΠ»Π½ΡΡΡΡΡ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΠΎ Π±ΡΡΡΡΠΎ. | |
|
133 | /// </summary> | |
|
120 | 134 | public event EventHandler<StateChangeEventArgs> StateChanged; |
|
121 | 135 | |
|
122 | 136 | /// <summary> |
@@ -130,6 +144,13 namespace Implab.Components { | |||
|
130 | 144 | /// </remarks> |
|
131 | 145 | public void Dispose() { |
|
132 | 146 | bool dispose = false; |
|
147 | lock (SynchronizationObject) { | |
|
148 | if (m_state != ExecutionState.Disposed) { | |
|
149 | dispose = true; | |
|
150 | m_state = ExecutionState.Disposed; | |
|
151 | m_cookie = new object(); | |
|
152 | } | |
|
153 | } | |
|
133 | 154 | if (dispose) { |
|
134 | 155 | Dispose(true); |
|
135 | 156 | GC.SuppressFinalize(this); |
@@ -152,7 +173,7 namespace Implab.Components { | |||
|
152 | 173 | public void Initialize() { |
|
153 | 174 | var cookie = new object(); |
|
154 | 175 | if (MoveInitialize(cookie)) |
|
155 | ScheduleTask(InitializeInternalAsync, CancellationToken.None, cookie); | |
|
176 | Safe.NoWait(ScheduleTask(InitializeInternalAsync, CancellationToken.None, cookie)); | |
|
156 | 177 | else |
|
157 | 178 | throw new InvalidOperationException(); |
|
158 | 179 | } |
@@ -173,19 +194,36 namespace Implab.Components { | |||
|
173 | 194 | public void Start(CancellationToken ct) { |
|
174 | 195 | var cookie = new object(); |
|
175 | 196 | if (MoveStart(cookie)) |
|
176 |
S |
|
|
197 | Safe.NoWait(ScheduleStartAndRun(ct, cookie)); | |
|
177 | 198 | else |
|
178 | 199 | throw new InvalidOperationException(); |
|
179 | 200 | } |
|
180 | 201 | |
|
202 | async Task ScheduleStartAndRun(CancellationToken ct, object cookie) { | |
|
203 | try { | |
|
204 | await ScheduleTask(StartInternalAsync, ct, cookie); | |
|
205 | RunInternal(); | |
|
206 | } catch (Exception err) { | |
|
207 | Fail(err); | |
|
208 | } | |
|
209 | } | |
|
210 | ||
|
181 | 211 | protected virtual Task StartInternalAsync(CancellationToken ct) { |
|
182 | 212 | return Task.CompletedTask; |
|
183 | 213 | } |
|
184 | 214 | |
|
215 | /// <summary> | |
|
216 | /// This method is called after the component is enetered running state, | |
|
217 | /// use this method to | |
|
218 | /// </summary> | |
|
219 | protected virtual void RunInternal() { | |
|
220 | ||
|
221 | } | |
|
222 | ||
|
185 | 223 | public void Stop(CancellationToken ct) { |
|
186 | 224 | var cookie = new object(); |
|
187 | 225 | if (MoveStop(cookie)) |
|
188 | ScheduleTask(StopAsync, ct, cookie); | |
|
226 | Safe.NoWait(ScheduleTask(StopAsync, ct, cookie)); | |
|
189 | 227 | else |
|
190 | 228 | throw new InvalidOperationException(); |
|
191 | 229 | } |
@@ -273,9 +311,9 namespace Implab.Components { | |||
|
273 | 311 | } |
|
274 | 312 | } |
|
275 | 313 | |
|
276 |
|
|
|
314 | Task ScheduleTask(Func<CancellationToken, Task> next, CancellationToken ct, object cookie) { | |
|
277 | 315 | |
|
278 |
|
|
|
316 | var op = AsyncOperationDescriptor.Create(async (x) => { | |
|
279 | 317 | try { |
|
280 | 318 | await next(x); |
|
281 | 319 | MoveSuccess(cookie); |
@@ -283,6 +321,9 namespace Implab.Components { | |||
|
283 | 321 | MoveFailed(e, cookie); |
|
284 | 322 | } |
|
285 | 323 | }, ct); |
|
324 | ||
|
325 | m_current = op; | |
|
326 | return op.Task; | |
|
286 | 327 | } |
|
287 | 328 | |
|
288 | 329 | #endregion |
General Comments 3
ok, latest stable version should be in default
You need to be logged in to leave comments.
Login now