annotate Implab/Components/RunnableComponent.cs @ 259:7d52dc684bbd v3

PollingComponent: implemented correct stopping
author cin
date Fri, 13 Apr 2018 03:57:39 +0300
parents 440801d88019
children 547a2fc0d93e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
1 using System;
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
2 using System.Diagnostics;
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
3 using System.Threading;
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
4 using System.Threading.Tasks;
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
5
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
6 namespace Implab.Components {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
7 /// <summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
8 /// Base class for implementing components which support start and stop operations,
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
9 /// such components may represent running services.
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
10 /// </summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
11 /// <remarks>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
12 /// This class provides a basic lifecycle from the creation to the
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
13 /// termination of the component.
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
14 /// </remarks>
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
15 public abstract class RunnableComponent : IAsyncComponent, IRunnable, IInitializable, IDisposable {
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
16
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
17 /// <summary>
252
6f4630d0bcd9 removed absolete Diagnostics classes
cin
parents: 251
diff changeset
18 /// This class bounds <see cref="CancellationTokenSource"/> lifetime to the task,
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
19 /// when the task completes the associated token source will be disposed.
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
20 /// </summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
21 class AsyncOperationDescriptor {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
22
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
23 public static AsyncOperationDescriptor None { get; } = new AsyncOperationDescriptor();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
24
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
25 readonly CancellationTokenSource m_cts;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
26
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
27 bool m_done;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
28
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
29 public CancellationToken Token {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
30 get { return m_cts == null ? CancellationToken.None : m_cts.Token; }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
31 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
32
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
33 public Task Task { get; private set; }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
34
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
35 private AsyncOperationDescriptor(Task task, CancellationTokenSource cts) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
36 m_cts = cts;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
37 Task = Chain(task);
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
38 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
39
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
40 private AsyncOperationDescriptor() {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
41 Task = Task.CompletedTask;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
42 }
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
43
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
44 public void Cancel() {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
45 if (m_cts != null) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
46 lock (m_cts) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
47 if (!m_done)
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
48 m_cts.Cancel();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
49 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
50 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
51 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
52
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
53 void Done() {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
54 if (m_cts != null) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
55 lock (m_cts) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
56 m_done = true;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
57 m_cts.Dispose();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
58 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
59 } else {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
60 m_done = true;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
61 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
62 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
63
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
64 async Task Chain(Task other) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
65 try {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
66 await other;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
67 } finally {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
68 Done();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
69 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
70 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
71
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
72 public static AsyncOperationDescriptor Create(Func<CancellationToken, Task> factory, CancellationToken ct) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
73 var cts = ct.CanBeCanceled ?
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
74 CancellationTokenSource.CreateLinkedTokenSource(ct) :
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
75 new CancellationTokenSource();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
76
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
77 return new AsyncOperationDescriptor(factory(cts.Token), cts);
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
78 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
79
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
80 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
81
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
82 // this lock is used to synchronize state flow of the component during
256
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
83 // processing calls from a client and internal processes.
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
84 readonly object m_lock = new object();
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
85
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
86 // current operation cookie, used to check wheather a call to
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
87 // MoveSuccess/MoveFailed method belongs to the current
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
88 // operation, if cookies didn't match ignore completion result.
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
89 object m_cookie;
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
90
256
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
91 // AsyncOperationDscriptor aggregates a task and it's cancellation token
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
92 AsyncOperationDescriptor m_current = AsyncOperationDescriptor.None;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
93
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
94 ExecutionState m_state;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
95
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
96 /// <summary>
440801d88019 working on runnable components
cin
parents: 256
diff changeset
97 /// Объект синхронизации используется для обеспечения совместного доступа
440801d88019 working on runnable components
cin
parents: 256
diff changeset
98 /// клиента компоненты и процессов, протекающих внутри компоненты, к общему
440801d88019 working on runnable components
cin
parents: 256
diff changeset
99 /// состоянию, т.е.true таким свойствам, как <see cref="State"/>,
440801d88019 working on runnable components
cin
parents: 256
diff changeset
100 /// <see cref="LastError"/>. Обработчики события <see cref="StateChanged"/>
440801d88019 working on runnable components
cin
parents: 256
diff changeset
101 /// вызываются уже с установленной блокировкой, поэтому дополнительная
440801d88019 working on runnable components
cin
parents: 256
diff changeset
102 /// синхронизация не требуется.
440801d88019 working on runnable components
cin
parents: 256
diff changeset
103 /// </summary>
440801d88019 working on runnable components
cin
parents: 256
diff changeset
104 public object SynchronizationObject { get { return m_lock; } }
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
105
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
106 protected RunnableComponent(bool initialized) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
107 State = initialized ? ExecutionState.Ready : ExecutionState.Created;
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
108 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
109
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
110 public Task Completion {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
111 get { return m_current.Task; }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
112 }
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
113
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
114 public ExecutionState State {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
115 get { return m_state; }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
116 private set {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
117 if (m_state != value) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
118 m_state = value;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
119 StateChanged.DispatchEvent(this, new StateChangeEventArgs {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
120 State = value,
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
121 LastError = LastError
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
122 });
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
123 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
124 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
125 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
126
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
127 public Exception LastError { get; private set; }
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
128
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
129 /// <summary>
440801d88019 working on runnable components
cin
parents: 256
diff changeset
130 /// Событие изменения состояния компоненты.see Обработчики данного события
440801d88019 working on runnable components
cin
parents: 256
diff changeset
131 /// вызываются внутри блокировки <see cref="SynchronizationObject"/> и должны
440801d88019 working on runnable components
cin
parents: 256
diff changeset
132 /// выполняться максимально быстро.
440801d88019 working on runnable components
cin
parents: 256
diff changeset
133 /// </summary>
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
134 public event EventHandler<StateChangeEventArgs> StateChanged;
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
135
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
136 /// <summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
137 /// Releases all resources used by the current component regardless of its
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
138 /// execution state.
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
139 /// </summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
140 /// <remarks>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
141 /// Calling to this method may result unexpedted results if the component
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
142 /// isn't in the stopped state. Call this method after the component is
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
143 /// stopped if needed or if the component is in the failed state.
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
144 /// </remarks>
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
145 public void Dispose() {
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
146 bool dispose = false;
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
147 lock (SynchronizationObject) {
440801d88019 working on runnable components
cin
parents: 256
diff changeset
148 if (m_state != ExecutionState.Disposed) {
440801d88019 working on runnable components
cin
parents: 256
diff changeset
149 dispose = true;
440801d88019 working on runnable components
cin
parents: 256
diff changeset
150 m_state = ExecutionState.Disposed;
440801d88019 working on runnable components
cin
parents: 256
diff changeset
151 m_cookie = new object();
440801d88019 working on runnable components
cin
parents: 256
diff changeset
152 }
440801d88019 working on runnable components
cin
parents: 256
diff changeset
153 }
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
154 if (dispose) {
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
155 Dispose(true);
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
156 GC.SuppressFinalize(this);
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
157 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
158 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
159
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
160 ~RunnableComponent() {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
161 Dispose(false);
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
162 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
163
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
164 /// <summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
165 /// Releases all resources used by the current component regardless of its
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
166 /// execution state.
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
167 /// </summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
168 /// <param name="disposing">Indicates that the component is disposed
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
169 /// during a normal disposing or during GC.</param>
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
170 protected virtual void Dispose(bool disposing) {
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
171 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
172
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
173 public void Initialize() {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
174 var cookie = new object();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
175 if (MoveInitialize(cookie))
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
176 Safe.NoWait(ScheduleTask(InitializeInternalAsync, CancellationToken.None, cookie));
256
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
177 else
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
178 throw new InvalidOperationException();
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
179 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
180
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
181 /// <summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
182 /// This method is used for initialization during a component creation.
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
183 /// </summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
184 /// <param name="ct">A cancellation token for this operation</param>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
185 /// <remarks>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
186 /// This method should be used for short and mostly syncronous operations,
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
187 /// other operations which require time to run shoud be placed in
252
6f4630d0bcd9 removed absolete Diagnostics classes
cin
parents: 251
diff changeset
188 /// <see cref="StartInternalAsync(CancellationToken)"/> method.
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
189 /// </remarks>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
190 protected virtual Task InitializeInternalAsync(CancellationToken ct) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
191 return Task.CompletedTask;
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
192 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
193
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
194 public void Start(CancellationToken ct) {
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
195 var cookie = new object();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
196 if (MoveStart(cookie))
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
197 Safe.NoWait(ScheduleStartAndRun(ct, cookie));
256
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
198 else
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
199 throw new InvalidOperationException();
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
200 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
201
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
202 async Task ScheduleStartAndRun(CancellationToken ct, object cookie) {
440801d88019 working on runnable components
cin
parents: 256
diff changeset
203 try {
440801d88019 working on runnable components
cin
parents: 256
diff changeset
204 await ScheduleTask(StartInternalAsync, ct, cookie);
440801d88019 working on runnable components
cin
parents: 256
diff changeset
205 RunInternal();
440801d88019 working on runnable components
cin
parents: 256
diff changeset
206 } catch (Exception err) {
440801d88019 working on runnable components
cin
parents: 256
diff changeset
207 Fail(err);
440801d88019 working on runnable components
cin
parents: 256
diff changeset
208 }
440801d88019 working on runnable components
cin
parents: 256
diff changeset
209 }
440801d88019 working on runnable components
cin
parents: 256
diff changeset
210
252
6f4630d0bcd9 removed absolete Diagnostics classes
cin
parents: 251
diff changeset
211 protected virtual Task StartInternalAsync(CancellationToken ct) {
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
212 return Task.CompletedTask;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
213 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
214
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
215 /// <summary>
440801d88019 working on runnable components
cin
parents: 256
diff changeset
216 /// This method is called after the component is enetered running state,
440801d88019 working on runnable components
cin
parents: 256
diff changeset
217 /// use this method to
440801d88019 working on runnable components
cin
parents: 256
diff changeset
218 /// </summary>
440801d88019 working on runnable components
cin
parents: 256
diff changeset
219 protected virtual void RunInternal() {
440801d88019 working on runnable components
cin
parents: 256
diff changeset
220
440801d88019 working on runnable components
cin
parents: 256
diff changeset
221 }
440801d88019 working on runnable components
cin
parents: 256
diff changeset
222
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
223 public void Stop(CancellationToken ct) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
224 var cookie = new object();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
225 if (MoveStop(cookie))
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
226 Safe.NoWait(ScheduleTask(StopAsync, ct, cookie));
256
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
227 else
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
228 throw new InvalidOperationException();
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
229 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
230
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
231 async Task StopAsync(CancellationToken ct) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
232 m_current.Cancel();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
233 await Completion;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
234
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
235 ct.ThrowIfCancellationRequested();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
236
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
237 await StopInternalAsync(ct);
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
238 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
239
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
240 protected virtual Task StopInternalAsync(CancellationToken ct) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
241 return Task.CompletedTask;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
242 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
243
256
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
244 protected void Fail(Exception err) {
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
245 lock(m_lock) {
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
246 if (m_state != ExecutionState.Running)
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
247 return;
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
248 m_cookie = new object();
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
249 LastError = err;
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
250 State = ExecutionState.Failed;
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
251 }
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
252 }
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
253
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
254
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
255 #region state management
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
256
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
257 bool MoveInitialize(object cookie) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
258 lock (m_lock) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
259 if (State != ExecutionState.Created)
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
260 return false;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
261 State = ExecutionState.Initializing;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
262 m_cookie = cookie;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
263 return true;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
264 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
265 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
266
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
267 bool MoveStart(object cookie) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
268 lock (m_lock) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
269 if (State != ExecutionState.Ready)
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
270 return false;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
271 State = ExecutionState.Starting;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
272 m_cookie = cookie;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
273 return true;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
274 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
275 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
276
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
277 bool MoveStop(object cookie) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
278 lock (m_lock) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
279 if (State != ExecutionState.Starting && State != ExecutionState.Running)
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
280 return false;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
281 State = ExecutionState.Stopping;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
282 m_cookie = cookie;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
283 return true;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
284 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
285 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
286
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
287 void MoveSuccess(object cookie) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
288 lock (m_lock) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
289 if (m_cookie != cookie)
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
290 return;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
291 switch (State) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
292 case ExecutionState.Initializing:
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
293 State = ExecutionState.Ready;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
294 break;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
295 case ExecutionState.Starting:
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
296 State = ExecutionState.Running;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
297 break;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
298 case ExecutionState.Stopping:
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
299 State = ExecutionState.Stopped;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
300 break;
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
301 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
302 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
303 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
304
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
305 void MoveFailed(Exception err, object cookie) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
306 lock (m_lock) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
307 if (m_cookie != cookie)
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
308 return;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
309 LastError = err;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
310 State = ExecutionState.Failed;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
311 }
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
312 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
313
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
314 Task ScheduleTask(Func<CancellationToken, Task> next, CancellationToken ct, object cookie) {
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
315
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
316 var op = AsyncOperationDescriptor.Create(async (x) => {
256
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
317 try {
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
318 await next(x);
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
319 MoveSuccess(cookie);
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
320 } catch (Exception e) {
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
321 MoveFailed(e, cookie);
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
322 }
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
323 }, ct);
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
324
440801d88019 working on runnable components
cin
parents: 256
diff changeset
325 m_current = op;
440801d88019 working on runnable components
cin
parents: 256
diff changeset
326 return op.Task;
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
327 }
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
328
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
329 #endregion
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
330 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
331 }