TaskFactory_T.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. //
  2. // TaskFactory_T.cs
  3. //
  4. // Authors:
  5. // Jérémie "Garuma" Laval <[email protected]>
  6. // Marek Safar <[email protected]>
  7. //
  8. // Copyright (c) 2009 Jérémie "Garuma" Laval
  9. // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
  10. //
  11. // Permission is hereby granted, free of charge, to any person obtaining a copy
  12. // of this software and associated documentation files (the "Software"), to deal
  13. // in the Software without restriction, including without limitation the rights
  14. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15. // copies of the Software, and to permit persons to whom the Software is
  16. // furnished to do so, subject to the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be included in
  19. // all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  24. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  26. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  27. // THE SOFTWARE.
  28. #if NET_4_0 || MOBILE
  29. namespace System.Threading.Tasks
  30. {
  31. public class TaskFactory<TResult>
  32. {
  33. readonly TaskScheduler scheduler;
  34. TaskCreationOptions creationOptions;
  35. TaskContinuationOptions continuationOptions;
  36. CancellationToken cancellationToken;
  37. TaskFactory parent;
  38. public TaskFactory ()
  39. : this (CancellationToken.None)
  40. {
  41. }
  42. public TaskFactory (TaskScheduler scheduler)
  43. : this (CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, scheduler)
  44. {
  45. }
  46. public TaskFactory (CancellationToken cancellationToken)
  47. : this (cancellationToken, TaskCreationOptions.None, TaskContinuationOptions.None, null)
  48. {
  49. }
  50. public TaskFactory (TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions)
  51. : this (CancellationToken.None, creationOptions, continuationOptions, null)
  52. {
  53. }
  54. public TaskFactory (CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
  55. {
  56. this.cancellationToken = cancellationToken;
  57. this.scheduler = scheduler;
  58. this.creationOptions = creationOptions;
  59. this.continuationOptions = continuationOptions;
  60. TaskFactory.CheckContinuationOptions (continuationOptions);
  61. this.parent = new TaskFactory (cancellationToken, creationOptions, continuationOptions, scheduler);
  62. }
  63. public TaskScheduler Scheduler {
  64. get {
  65. return scheduler;
  66. }
  67. }
  68. public TaskContinuationOptions ContinuationOptions {
  69. get {
  70. return continuationOptions;
  71. }
  72. }
  73. public TaskCreationOptions CreationOptions {
  74. get {
  75. return creationOptions;
  76. }
  77. }
  78. public CancellationToken CancellationToken {
  79. get {
  80. return cancellationToken;
  81. }
  82. }
  83. #region StartNew for Task<TResult>
  84. public Task<TResult> StartNew (Func<TResult> function)
  85. {
  86. return StartNew (function, cancellationToken, creationOptions, GetScheduler ());
  87. }
  88. public Task<TResult> StartNew (Func<TResult> function, TaskCreationOptions creationOptions)
  89. {
  90. return StartNew (function, cancellationToken, creationOptions, GetScheduler ());
  91. }
  92. public Task<TResult> StartNew (Func<TResult> function, CancellationToken cancellationToken)
  93. {
  94. return StartNew (function, cancellationToken, creationOptions, GetScheduler ());
  95. }
  96. public Task<TResult> StartNew (Func<TResult> function,
  97. CancellationToken cancellationToken,
  98. TaskCreationOptions creationOptions,
  99. TaskScheduler scheduler)
  100. {
  101. return StartNew ((o) => function (), null, cancellationToken, creationOptions, scheduler);
  102. }
  103. public Task<TResult> StartNew (Func<object, TResult> function, object state)
  104. {
  105. return StartNew (function, state, cancellationToken, creationOptions, GetScheduler ());
  106. }
  107. public Task<TResult> StartNew (Func<object, TResult> function, object state, TaskCreationOptions creationOptions)
  108. {
  109. return StartNew (function, state, cancellationToken, creationOptions, GetScheduler ());
  110. }
  111. public Task<TResult> StartNew (Func<object, TResult> function, object state, CancellationToken cancellationToken)
  112. {
  113. return StartNew (function, state, cancellationToken, creationOptions, GetScheduler ());
  114. }
  115. public Task<TResult> StartNew (Func<object, TResult> function, object state,
  116. CancellationToken cancellationToken,
  117. TaskCreationOptions creationOptions,
  118. TaskScheduler scheduler)
  119. {
  120. return parent.StartNew<TResult> (function, state, cancellationToken, creationOptions, scheduler);
  121. }
  122. #endregion
  123. #region Continue
  124. public Task<TResult> ContinueWhenAny (Task[] tasks,
  125. Func<Task, TResult> continuationFunction)
  126. {
  127. return ContinueWhenAny (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
  128. }
  129. public Task<TResult> ContinueWhenAny (Task[] tasks,
  130. Func<Task, TResult> continuationFunction,
  131. CancellationToken cancellationToken)
  132. {
  133. return ContinueWhenAny (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
  134. }
  135. public Task<TResult> ContinueWhenAny (Task[] tasks,
  136. Func<Task, TResult> continuationFunction,
  137. TaskContinuationOptions continuationOptions)
  138. {
  139. return ContinueWhenAny (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
  140. }
  141. public Task<TResult> ContinueWhenAny (Task[] tasks,
  142. Func<Task, TResult> continuationFunction,
  143. CancellationToken cancellationToken,
  144. TaskContinuationOptions continuationOptions,
  145. TaskScheduler scheduler)
  146. {
  147. return parent.ContinueWhenAny (tasks, continuationFunction, cancellationToken, continuationOptions, scheduler);
  148. }
  149. public Task<TResult> ContinueWhenAny<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
  150. Func<Task<TAntecedentResult>, TResult> continuationFunction)
  151. {
  152. return ContinueWhenAny (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
  153. }
  154. public Task<TResult> ContinueWhenAny<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
  155. Func<Task<TAntecedentResult>, TResult> continuationFunction,
  156. CancellationToken cancellationToken)
  157. {
  158. return ContinueWhenAny (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
  159. }
  160. public Task<TResult> ContinueWhenAny<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
  161. Func<Task<TAntecedentResult>, TResult> continuationFunction,
  162. TaskContinuationOptions continuationOptions)
  163. {
  164. return ContinueWhenAny (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
  165. }
  166. public Task<TResult> ContinueWhenAny<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
  167. Func<Task<TAntecedentResult>, TResult> continuationFunction,
  168. CancellationToken cancellationToken,
  169. TaskContinuationOptions continuationOptions,
  170. TaskScheduler scheduler)
  171. {
  172. return parent.ContinueWhenAny (tasks, continuationFunction, cancellationToken, continuationOptions, scheduler);
  173. }
  174. public Task<TResult> ContinueWhenAll (Task[] tasks, Func<Task[], TResult> continuationFunction)
  175. {
  176. return ContinueWhenAll (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
  177. }
  178. public Task<TResult> ContinueWhenAll (Task[] tasks,
  179. Func<Task[], TResult> continuationFunction,
  180. TaskContinuationOptions continuationOptions)
  181. {
  182. return ContinueWhenAll (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
  183. }
  184. public Task<TResult> ContinueWhenAll (Task[] tasks,
  185. Func<Task[], TResult> continuationFunction,
  186. CancellationToken cancellationToken)
  187. {
  188. return ContinueWhenAll (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
  189. }
  190. public Task<TResult> ContinueWhenAll (Task[] tasks,
  191. Func<Task[], TResult> continuationFunction,
  192. CancellationToken cancellationToken,
  193. TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
  194. {
  195. return parent.ContinueWhenAll (tasks, continuationFunction, cancellationToken, continuationOptions, scheduler);
  196. }
  197. public Task<TResult> ContinueWhenAll<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
  198. Func<Task<TAntecedentResult>[], TResult> continuationFunction)
  199. {
  200. return ContinueWhenAll (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
  201. }
  202. public Task<TResult> ContinueWhenAll<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
  203. Func<Task<TAntecedentResult>[], TResult> continuationFunction,
  204. TaskContinuationOptions continuationOptions)
  205. {
  206. return ContinueWhenAll (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
  207. }
  208. public Task<TResult> ContinueWhenAll<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
  209. Func<Task<TAntecedentResult>[], TResult> continuationFunction,
  210. CancellationToken cancellationToken)
  211. {
  212. return ContinueWhenAll (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
  213. }
  214. public Task<TResult> ContinueWhenAll<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
  215. Func<Task<TAntecedentResult>[], TResult> continuationFunction,
  216. CancellationToken cancellationToken,
  217. TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
  218. {
  219. return parent.ContinueWhenAll (tasks, continuationFunction, cancellationToken, continuationOptions, scheduler);
  220. }
  221. #endregion
  222. #region FromAsync
  223. public Task<TResult> FromAsync (IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod)
  224. {
  225. return FromAsync (asyncResult, endMethod, creationOptions);
  226. }
  227. public Task<TResult> FromAsync (IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod, TaskCreationOptions creationOptions)
  228. {
  229. return FromAsync (asyncResult, endMethod, creationOptions, GetScheduler ());
  230. }
  231. public Task<TResult> FromAsync (IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod, TaskCreationOptions creationOptions, TaskScheduler scheduler)
  232. {
  233. return FromIAsyncResult (asyncResult, endMethod, creationOptions, scheduler);
  234. }
  235. internal static Task<TResult> FromIAsyncResult (IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod, TaskCreationOptions creationOptions, TaskScheduler scheduler)
  236. {
  237. if (asyncResult == null)
  238. throw new ArgumentNullException ("asyncResult");
  239. if (endMethod == null)
  240. throw new ArgumentNullException ("endMethod");
  241. if (scheduler == null)
  242. throw new ArgumentNullException ("scheduler");
  243. if ((creationOptions & Task.WorkerTaskNotSupportedOptions) != 0)
  244. throw new ArgumentOutOfRangeException ("creationOptions");
  245. var source = new CancellationTokenSource ();
  246. var task = new Task<TResult> (l => {
  247. try {
  248. return endMethod (asyncResult);
  249. } catch (OperationCanceledException) {
  250. source.Cancel ();
  251. source.Token.ThrowIfCancellationRequested ();
  252. }
  253. return default (TResult);
  254. }, null, source.Token, creationOptions);
  255. // Take quick path for completed operations
  256. if (asyncResult.IsCompleted) {
  257. task.RunSynchronously (scheduler);
  258. } else {
  259. ThreadPool.RegisterWaitForSingleObject (asyncResult.AsyncWaitHandle,
  260. (s, t) => task.RunSynchronously (scheduler),
  261. null, Timeout.Infinite, true);
  262. }
  263. return task;
  264. }
  265. public Task<TResult> FromAsync (Func<AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
  266. object state)
  267. {
  268. return FromAsync (beginMethod, endMethod, state, creationOptions);
  269. }
  270. public Task<TResult> FromAsync (Func<AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
  271. object state, TaskCreationOptions creationOptions)
  272. {
  273. return FromAsyncBeginEnd (beginMethod, endMethod, state, creationOptions);
  274. }
  275. internal static Task<TResult> FromAsyncBeginEnd (Func<AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
  276. object state, TaskCreationOptions creationOptions)
  277. {
  278. if (beginMethod == null)
  279. throw new ArgumentNullException ("beginMethod");
  280. if (endMethod == null)
  281. throw new ArgumentNullException ("endMethod");
  282. if ((creationOptions & Task.WorkerTaskNotSupportedOptions) != 0)
  283. throw new ArgumentOutOfRangeException ("creationOptions");
  284. var tcs = new TaskCompletionSource<TResult> (state, creationOptions);
  285. beginMethod (l => InnerInvoke (tcs, endMethod, l), state);
  286. return tcs.Task;
  287. }
  288. public Task<TResult> FromAsync<TArg1> (Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
  289. TArg1 arg1, object state)
  290. {
  291. return FromAsync (beginMethod, endMethod, arg1, state, creationOptions);
  292. }
  293. public Task<TResult> FromAsync<TArg1> (Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
  294. TArg1 arg1, object state, TaskCreationOptions creationOptions)
  295. {
  296. return FromAsyncBeginEnd (beginMethod, endMethod, arg1, state, creationOptions);
  297. }
  298. internal static Task<TResult> FromAsyncBeginEnd<TArg1> (Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
  299. Func<IAsyncResult, TResult> endMethod,
  300. TArg1 arg1, object state, TaskCreationOptions creationOptions)
  301. {
  302. if (beginMethod == null)
  303. throw new ArgumentNullException ("beginMethod");
  304. if (endMethod == null)
  305. throw new ArgumentNullException ("endMethod");
  306. if ((creationOptions & Task.WorkerTaskNotSupportedOptions) != 0)
  307. throw new ArgumentOutOfRangeException ("creationOptions");
  308. var tcs = new TaskCompletionSource<TResult> (state, creationOptions);
  309. beginMethod (arg1, l => InnerInvoke (tcs, endMethod, l), state);
  310. return tcs.Task;
  311. }
  312. public Task<TResult> FromAsync<TArg1, TArg2> (Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
  313. TArg1 arg1, TArg2 arg2, object state)
  314. {
  315. return FromAsync (beginMethod, endMethod, arg1, arg2, state, creationOptions);
  316. }
  317. public Task<TResult> FromAsync<TArg1, TArg2> (Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
  318. TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
  319. {
  320. return FromAsyncBeginEnd (beginMethod, endMethod, arg1, arg2, state, creationOptions);
  321. }
  322. internal static Task<TResult> FromAsyncBeginEnd<TArg1, TArg2> (Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
  323. TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
  324. {
  325. if (beginMethod == null)
  326. throw new ArgumentNullException ("beginMethod");
  327. if (endMethod == null)
  328. throw new ArgumentNullException ("endMethod");
  329. if ((creationOptions & Task.WorkerTaskNotSupportedOptions) != 0)
  330. throw new ArgumentOutOfRangeException ("creationOptions");
  331. var tcs = new TaskCompletionSource<TResult> (state, creationOptions);
  332. beginMethod (arg1, arg2, l => InnerInvoke (tcs, endMethod, l), state);
  333. return tcs.Task;
  334. }
  335. public Task<TResult> FromAsync<TArg1, TArg2, TArg3> (Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
  336. TArg1 arg1, TArg2 arg2, TArg3 arg3, object state)
  337. {
  338. return FromAsync (beginMethod, endMethod, arg1, arg2, arg3, state, creationOptions);
  339. }
  340. public Task<TResult> FromAsync<TArg1, TArg2, TArg3> (Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
  341. TArg1 arg1, TArg2 arg2, TArg3 arg3, object state,
  342. TaskCreationOptions creationOptions)
  343. {
  344. return FromAsyncBeginEnd (beginMethod, endMethod, arg1, arg2, arg3, state, creationOptions);
  345. }
  346. internal static Task<TResult> FromAsyncBeginEnd<TArg1, TArg2, TArg3> (Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
  347. TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
  348. {
  349. if (beginMethod == null)
  350. throw new ArgumentNullException ("beginMethod");
  351. if (endMethod == null)
  352. throw new ArgumentNullException ("endMethod");
  353. if ((creationOptions & Task.WorkerTaskNotSupportedOptions) != 0)
  354. throw new ArgumentOutOfRangeException ("creationOptions");
  355. var tcs = new TaskCompletionSource<TResult> (state, creationOptions);
  356. beginMethod (arg1, arg2, arg3, l => InnerInvoke (tcs, endMethod, l), state);
  357. return tcs.Task;
  358. }
  359. #endregion
  360. TaskScheduler GetScheduler ()
  361. {
  362. return scheduler ?? TaskScheduler.Current;
  363. }
  364. static void InnerInvoke (TaskCompletionSource<TResult> tcs, Func<IAsyncResult, TResult> endMethod, IAsyncResult l)
  365. {
  366. try {
  367. tcs.SetResult (endMethod (l));
  368. } catch (OperationCanceledException) {
  369. tcs.SetCanceled ();
  370. } catch (Exception e) {
  371. tcs.SetException (e);
  372. }
  373. }
  374. }
  375. }
  376. #endif