1 //--------------------------------------------------------------------------
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // File: TaskFactoryExtensions_Delayed.cs
7 //--------------------------------------------------------------------------
9 namespace System.Threading.Tasks
11 public static partial class TaskFactoryExtensions
13 #region TaskFactory No Action
14 /// <summary>Creates a Task that will complete after the specified delay.</summary>
15 /// <param name="factory">The TaskFactory.</param>
16 /// <param name="millisecondsDelay">The delay after which the Task should transition to RanToCompletion.</param>
17 /// <returns>A Task that will be completed after the specified duration.</returns>
18 public static Task StartNewDelayed(
19 this TaskFactory factory, int millisecondsDelay)
21 return StartNewDelayed(factory, millisecondsDelay, CancellationToken.None);
24 /// <summary>Creates a Task that will complete after the specified delay.</summary>
25 /// <param name="factory">The TaskFactory.</param>
26 /// <param name="millisecondsDelay">The delay after which the Task should transition to RanToCompletion.</param>
27 /// <param name="cancellationToken">The cancellation token that can be used to cancel the timed task.</param>
28 /// <returns>A Task that will be completed after the specified duration and that's cancelable with the specified token.</returns>
29 public static Task StartNewDelayed(this TaskFactory factory, int millisecondsDelay, CancellationToken cancellationToken)
32 if (factory == null) throw new ArgumentNullException("factory");
33 if (millisecondsDelay < 0) throw new ArgumentOutOfRangeException("millisecondsDelay");
35 // Create the timed task
36 var tcs = new TaskCompletionSource<object>(factory.CreationOptions);
37 var ctr = default(CancellationTokenRegistration);
39 // Create the timer but don't start it yet. If we start it now,
40 // it might fire before ctr has been set to the right registration.
41 var timer = new Timer(self =>
43 // Clean up both the cancellation token and the timer, and try to transition to completed
45 ((Timer)self).Dispose();
46 tcs.TrySetResult(null);
49 // Register with the cancellation token.
50 if (cancellationToken.CanBeCanceled)
52 // When cancellation occurs, cancel the timer and try to transition to canceled.
53 // There could be a race, but it's benign.
54 ctr = cancellationToken.Register(() =>
61 // Start the timer and hand back the task...
62 timer.Change(millisecondsDelay, Timeout.Infinite);
67 #region TaskFactory with Action
68 /// <summary>Creates and schedules a task for execution after the specified time delay.</summary>
69 /// <param name="factory">The factory to use to create the task.</param>
70 /// <param name="millisecondsDelay">The delay after which the task will be scheduled.</param>
71 /// <param name="action">The delegate executed by the task.</param>
72 /// <returns>The created Task.</returns>
73 public static Task StartNewDelayed(
74 this TaskFactory factory,
75 int millisecondsDelay, Action action)
77 if (factory == null) throw new ArgumentNullException("factory");
78 return StartNewDelayed(factory, millisecondsDelay, action, factory.CancellationToken, factory.CreationOptions, factory.GetTargetScheduler());
81 /// <summary>Creates and schedules a task for execution after the specified time delay.</summary>
82 /// <param name="factory">The factory to use to create the task.</param>
83 /// <param name="millisecondsDelay">The delay after which the task will be scheduled.</param>
84 /// <param name="action">The delegate executed by the task.</param>
85 /// <param name="creationOptions">Options that control the task's behavior.</param>
86 /// <returns>The created Task.</returns>
87 public static Task StartNewDelayed(
88 this TaskFactory factory,
89 int millisecondsDelay, Action action,
90 TaskCreationOptions creationOptions)
92 if (factory == null) throw new ArgumentNullException("factory");
93 return StartNewDelayed(factory, millisecondsDelay, action, factory.CancellationToken, creationOptions, factory.GetTargetScheduler());
96 /// <summary>Creates and schedules a task for execution after the specified time delay.</summary>
97 /// <param name="factory">The factory to use to create the task.</param>
98 /// <param name="millisecondsDelay">The delay after which the task will be scheduled.</param>
99 /// <param name="action">The delegate executed by the task.</param>
100 /// <param name="cancellationToken">The cancellation token to assign to the created Task.</param>
101 /// <returns>The created Task.</returns>
102 public static Task StartNewDelayed(
103 this TaskFactory factory,
104 int millisecondsDelay, Action action,
105 CancellationToken cancellationToken)
107 if (factory == null) throw new ArgumentNullException("factory");
108 return StartNewDelayed(factory, millisecondsDelay, action, cancellationToken, factory.CreationOptions, factory.GetTargetScheduler());
111 /// <summary>Creates and schedules a task for execution after the specified time delay.</summary>
112 /// <param name="factory">The factory to use to create the task.</param>
113 /// <param name="millisecondsDelay">The delay after which the task will be scheduled.</param>
114 /// <param name="action">The delegate executed by the task.</param>
115 /// <param name="cancellationToken">The cancellation token to assign to the created Task.</param>
116 /// <param name="creationOptions">Options that control the task's behavior.</param>
117 /// <param name="scheduler">The scheduler to which the Task will be scheduled.</param>
118 /// <returns>The created Task.</returns>
119 public static Task StartNewDelayed(
120 this TaskFactory factory,
121 int millisecondsDelay, Action action,
122 CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
124 if (factory == null) throw new ArgumentNullException("factory");
125 if (millisecondsDelay < 0) throw new ArgumentOutOfRangeException("millisecondsDelay");
126 if (action == null) throw new ArgumentNullException("action");
127 if (scheduler == null) throw new ArgumentNullException("scheduler");
130 .StartNewDelayed(millisecondsDelay, cancellationToken)
131 .ContinueWith(_ => action(), cancellationToken, TaskContinuationOptions.OnlyOnRanToCompletion, scheduler);
134 /// <summary>Creates and schedules a task for execution after the specified time delay.</summary>
135 /// <param name="factory">The factory to use to create the task.</param>
136 /// <param name="millisecondsDelay">The delay after which the task will be scheduled.</param>
137 /// <param name="action">The delegate executed by the task.</param>
138 /// <param name="state">An object provided to the delegate.</param>
139 /// <returns>The created Task.</returns>
140 public static Task StartNewDelayed(
141 this TaskFactory factory,
142 int millisecondsDelay, Action<object> action, object state)
144 if (factory == null) throw new ArgumentNullException("factory");
145 return StartNewDelayed(factory, millisecondsDelay, action, state, factory.CancellationToken, factory.CreationOptions, factory.GetTargetScheduler());
148 /// <summary>Creates and schedules a task for execution after the specified time delay.</summary>
149 /// <param name="factory">The factory to use to create the task.</param>
150 /// <param name="millisecondsDelay">The delay after which the task will be scheduled.</param>
151 /// <param name="action">The delegate executed by the task.</param>
152 /// <param name="state">An object provided to the delegate.</param>
153 /// <param name="creationOptions">Options that control the task's behavior.</param>
154 /// <returns>The created Task.</returns>
155 public static Task StartNewDelayed(
156 this TaskFactory factory,
157 int millisecondsDelay, Action<object> action, object state,
158 TaskCreationOptions creationOptions)
160 if (factory == null) throw new ArgumentNullException("factory");
161 return StartNewDelayed(factory, millisecondsDelay, action, state, factory.CancellationToken, creationOptions, factory.GetTargetScheduler());
164 /// <summary>Creates and schedules a task for execution after the specified time delay.</summary>
165 /// <param name="factory">The factory to use to create the task.</param>
166 /// <param name="millisecondsDelay">The delay after which the task will be scheduled.</param>
167 /// <param name="action">The delegate executed by the task.</param>
168 /// <param name="state">An object provided to the delegate.</param>
169 /// <param name="cancellationToken">The cancellation token to assign to the created Task.</param>
170 /// <returns>The created Task.</returns>
171 public static Task StartNewDelayed(
172 this TaskFactory factory,
173 int millisecondsDelay, Action<object> action, object state,
174 CancellationToken cancellationToken)
176 if (factory == null) throw new ArgumentNullException("factory");
177 return StartNewDelayed(factory, millisecondsDelay, action, state, cancellationToken, factory.CreationOptions, factory.GetTargetScheduler());
180 /// <summary>Creates and schedules a task for execution after the specified time delay.</summary>
181 /// <param name="factory">The factory to use to create the task.</param>
182 /// <param name="millisecondsDelay">The delay after which the task will be scheduled.</param>
183 /// <param name="action">The delegate executed by the task.</param>
184 /// <param name="state">An object provided to the delegate.</param>
185 /// <param name="cancellationToken">The cancellation token to assign to the created Task.</param>
186 /// <param name="creationOptions">Options that control the task's behavior.</param>
187 /// <param name="scheduler">The scheduler to which the Task will be scheduled.</param>
188 /// <returns>The created Task.</returns>
189 public static Task StartNewDelayed(
190 this TaskFactory factory,
191 int millisecondsDelay, Action<object> action, object state,
192 CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
194 if (factory == null) throw new ArgumentNullException("factory");
195 if (millisecondsDelay < 0) throw new ArgumentOutOfRangeException("millisecondsDelay");
196 if (action == null) throw new ArgumentNullException("action");
197 if (scheduler == null) throw new ArgumentNullException("scheduler");
199 // Create the task that will be returned; workaround for no ContinueWith(..., state) overload.
200 var result = new TaskCompletionSource<object>(state);
202 // Delay a continuation to run the action
204 .StartNewDelayed(millisecondsDelay, cancellationToken)
207 if (t.IsCanceled) result.TrySetCanceled();
213 result.TrySetResult(null);
215 catch (Exception exc) { result.TrySetException(exc); }
224 #region TaskFactory<TResult> with Func
225 /// <summary>Creates and schedules a task for execution after the specified time delay.</summary>
226 /// <param name="factory">The factory to use to create the task.</param>
227 /// <param name="millisecondsDelay">The delay after which the task will be scheduled.</param>
228 /// <param name="function">The delegate executed by the task.</param>
229 /// <returns>The created Task.</returns>
230 public static Task<TResult> StartNewDelayed<TResult>(
231 this TaskFactory<TResult> factory,
232 int millisecondsDelay, Func<TResult> function)
234 if (factory == null) throw new ArgumentNullException("factory");
235 return StartNewDelayed(factory, millisecondsDelay, function, factory.CancellationToken, factory.CreationOptions, factory.GetTargetScheduler());
238 /// <summary>Creates and schedules a task for execution after the specified time delay.</summary>
239 /// <param name="factory">The factory to use to create the task.</param>
240 /// <param name="millisecondsDelay">The delay after which the task will be scheduled.</param>
241 /// <param name="function">The delegate executed by the task.</param>
242 /// <param name="creationOptions">Options that control the task's behavior.</param>
243 /// <returns>The created Task.</returns>
244 public static Task<TResult> StartNewDelayed<TResult>(
245 this TaskFactory<TResult> factory,
246 int millisecondsDelay, Func<TResult> function,
247 TaskCreationOptions creationOptions)
249 if (factory == null) throw new ArgumentNullException("factory");
250 return StartNewDelayed(factory, millisecondsDelay, function, factory.CancellationToken, creationOptions, factory.GetTargetScheduler());
253 /// <summary>Creates and schedules a task for execution after the specified time delay.</summary>
254 /// <param name="factory">The factory to use to create the task.</param>
255 /// <param name="millisecondsDelay">The delay after which the task will be scheduled.</param>
256 /// <param name="function">The delegate executed by the task.</param>
257 /// <param name="cancellationToken">The CancellationToken to assign to the Task.</param>
258 /// <returns>The created Task.</returns>
259 public static Task<TResult> StartNewDelayed<TResult>(
260 this TaskFactory<TResult> factory,
261 int millisecondsDelay, Func<TResult> function,
262 CancellationToken cancellationToken)
264 if (factory == null) throw new ArgumentNullException("factory");
265 return StartNewDelayed(factory, millisecondsDelay, function, cancellationToken, factory.CreationOptions, factory.GetTargetScheduler());
268 /// <summary>Creates and schedules a task for execution after the specified time delay.</summary>
269 /// <param name="factory">The factory to use to create the task.</param>
270 /// <param name="millisecondsDelay">The delay after which the task will be scheduled.</param>
271 /// <param name="function">The delegate executed by the task.</param>
272 /// <param name="cancellationToken">The CancellationToken to assign to the Task.</param>
273 /// <param name="creationOptions">Options that control the task's behavior.</param>
274 /// <param name="scheduler">The scheduler to which the Task will be scheduled.</param>
275 /// <returns>The created Task.</returns>
276 public static Task<TResult> StartNewDelayed<TResult>(
277 this TaskFactory<TResult> factory,
278 int millisecondsDelay, Func<TResult> function,
279 CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
281 if (factory == null) throw new ArgumentNullException("factory");
282 if (millisecondsDelay < 0) throw new ArgumentOutOfRangeException("millisecondsDelay");
283 if (function == null) throw new ArgumentNullException("function");
284 if (scheduler == null) throw new ArgumentNullException("scheduler");
286 // Create the trigger and the timer to start it
287 var tcs = new TaskCompletionSource<object>();
288 var timer = new Timer(obj => ((TaskCompletionSource<object>)obj).SetResult(null),
289 tcs, millisecondsDelay, Timeout.Infinite);
291 // Return a task that executes the function when the trigger fires
292 return tcs.Task.ContinueWith(_ =>
296 }, cancellationToken, ContinuationOptionsFromCreationOptions(creationOptions), scheduler);
299 /// <summary>Creates and schedules a task for execution after the specified time delay.</summary>
300 /// <param name="factory">The factory to use to create the task.</param>
301 /// <param name="millisecondsDelay">The delay after which the task will be scheduled.</param>
302 /// <param name="function">The delegate executed by the task.</param>
303 /// <param name="state">An object provided to the delegate.</param>
304 /// <returns>The created Task.</returns>
305 public static Task<TResult> StartNewDelayed<TResult>(
306 this TaskFactory<TResult> factory,
307 int millisecondsDelay, Func<object, TResult> function, object state)
309 if (factory == null) throw new ArgumentNullException("factory");
310 return StartNewDelayed(factory, millisecondsDelay, function, state, factory.CancellationToken, factory.CreationOptions, factory.GetTargetScheduler());
313 /// <summary>Creates and schedules a task for execution after the specified time delay.</summary>
314 /// <param name="factory">The factory to use to create the task.</param>
315 /// <param name="millisecondsDelay">The delay after which the task will be scheduled.</param>
316 /// <param name="function">The delegate executed by the task.</param>
317 /// <param name="state">An object provided to the delegate.</param>
318 /// <param name="cancellationToken">The CancellationToken to assign to the Task.</param>
319 /// <returns>The created Task.</returns>
320 public static Task<TResult> StartNewDelayed<TResult>(
321 this TaskFactory<TResult> factory,
322 int millisecondsDelay, Func<object, TResult> function, object state,
323 CancellationToken cancellationToken)
325 if (factory == null) throw new ArgumentNullException("factory");
326 return StartNewDelayed(factory, millisecondsDelay, function, state, cancellationToken, factory.CreationOptions, factory.GetTargetScheduler());
329 /// <summary>Creates and schedules a task for execution after the specified time delay.</summary>
330 /// <param name="factory">The factory to use to create the task.</param>
331 /// <param name="millisecondsDelay">The delay after which the task will be scheduled.</param>
332 /// <param name="function">The delegate executed by the task.</param>
333 /// <param name="state">An object provided to the delegate.</param>
334 /// <param name="creationOptions">Options that control the task's behavior.</param>
335 /// <returns>The created Task.</returns>
336 public static Task<TResult> StartNewDelayed<TResult>(
337 this TaskFactory<TResult> factory,
338 int millisecondsDelay, Func<object, TResult> function, object state,
339 TaskCreationOptions creationOptions)
341 if (factory == null) throw new ArgumentNullException("factory");
342 return StartNewDelayed(factory, millisecondsDelay, function, state, factory.CancellationToken, creationOptions, factory.GetTargetScheduler());
345 /// <summary>Creates and schedules a task for execution after the specified time delay.</summary>
346 /// <param name="factory">The factory to use to create the task.</param>
347 /// <param name="millisecondsDelay">The delay after which the task will be scheduled.</param>
348 /// <param name="function">The delegate executed by the task.</param>
349 /// <param name="state">An object provided to the delegate.</param>
350 /// <param name="cancellationToken">The CancellationToken to assign to the Task.</param>
351 /// <param name="creationOptions">Options that control the task's behavior.</param>
352 /// <param name="scheduler">The scheduler to which the Task will be scheduled.</param>
353 /// <returns>The created Task.</returns>
354 public static Task<TResult> StartNewDelayed<TResult>(
355 this TaskFactory<TResult> factory,
356 int millisecondsDelay, Func<object, TResult> function, object state,
357 CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
359 if (factory == null) throw new ArgumentNullException("factory");
360 if (millisecondsDelay < 0) throw new ArgumentOutOfRangeException("millisecondsDelay");
361 if (function == null) throw new ArgumentNullException("action");
362 if (scheduler == null) throw new ArgumentNullException("scheduler");
364 // Create the task that will be returned
365 var result = new TaskCompletionSource<TResult>(state);
368 // Create the task that will run the user's function
369 var functionTask = new Task<TResult>(function, state, creationOptions);
371 // When the function task completes, transfer the results to the returned task
372 functionTask.ContinueWith(t =>
374 result.SetFromTask(t);
376 }, cancellationToken, ContinuationOptionsFromCreationOptions(creationOptions) | TaskContinuationOptions.ExecuteSynchronously, scheduler);
378 // Start the timer for the trigger
379 timer = new Timer(obj => ((Task)obj).Start(scheduler),
380 functionTask, millisecondsDelay, Timeout.Infinite);