1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 6 // 7 // AsyncWork.cs 8 // 9 // Helper class that is used to test the FromAsync method. These classes hold the APM patterns 10 // and is used by the TaskFromAsyncTest.cs file 11 // 12 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 13 14 using System; 15 using System.Collections.Generic; 16 using System.Collections.ObjectModel; 17 using System.Threading; 18 using System.Threading.Tasks; 19 20 namespace System.Threading.Tasks.Tests 21 { 22 #region AsyncWork (base) 23 24 /// <summary> 25 /// The abstract that defines the work done by the Async method 26 /// </summary> 27 public abstract class AsyncWork 28 { 29 /// <summary> 30 /// Defines the amount of time the thread should sleep (to simulate workload) 31 /// </summary> 32 private const int DEFAULT_TIME = 15; 33 private List<object> _inputs; 34 35 AsyncWork()36 public AsyncWork() 37 { 38 _inputs = new List<object>(); 39 } 40 AddInput(object o)41 protected void AddInput(object o) 42 { 43 _inputs.Add(o); 44 } 45 InvokeAction(bool throwing)46 protected void InvokeAction(bool throwing) 47 { 48 // 49 // simulate some dummy workload 50 // 51 var task = Task.Delay(DEFAULT_TIME); 52 task.Wait(); 53 54 if (throwing) //simulates error condition during the execution of user delegate 55 { 56 throw new TPLTestException(); 57 } 58 } 59 InvokeFunc(bool throwing)60 protected ReadOnlyCollection<object> InvokeFunc(bool throwing) 61 { 62 // 63 // simulate some dummy workload 64 // 65 var task = Task.Delay(DEFAULT_TIME); 66 task.Wait(); 67 68 if (throwing) 69 { 70 throw new TPLTestException(); 71 } 72 73 return Inputs; 74 } 75 CheckState(object o)76 protected void CheckState(object o) 77 { 78 ObservedState = o; 79 80 ObservedTaskScheduler = TaskScheduler.Current; 81 } 82 83 public ReadOnlyCollection<object> Inputs 84 { 85 get 86 { 87 return new ReadOnlyCollection<object>(_inputs); 88 } 89 } 90 91 public object ObservedState 92 { 93 get; 94 private set; 95 } 96 97 public object ObservedTaskScheduler 98 { 99 get; 100 private set; 101 } 102 } 103 104 #endregion 105 106 #region AsyncAction 107 108 /// <summary> 109 /// Extends the base class to implement that action form of APM 110 /// </summary> 111 public class AsyncAction : AsyncWork 112 { 113 private Action _action; 114 115 // a general action to take-in inputs upfront rather than delayed until BeginInvoke 116 // for testing the overload taking IAsyncResult AsyncAction(object[] inputs, bool throwing)117 public AsyncAction(object[] inputs, bool throwing) 118 : base() 119 { 120 _action = () => 121 { 122 foreach (object o in inputs) 123 { 124 AddInput(o); 125 } 126 127 InvokeAction(throwing); 128 }; 129 } 130 AsyncAction(bool throwing)131 public AsyncAction(bool throwing) 132 : base() 133 { 134 _action = () => 135 { 136 InvokeAction(throwing); 137 }; 138 } 139 140 #region APM 141 BeginInvoke(AsyncCallback cb, object state)142 public IAsyncResult BeginInvoke(AsyncCallback cb, object state) 143 { 144 Task task = Task.Factory.StartNew(_ => _action(), state, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default); 145 task.ContinueWith(_ => cb(task)); 146 return task; 147 } 148 EndInvoke(IAsyncResult iar)149 public void EndInvoke(IAsyncResult iar) 150 { 151 CheckState(iar.AsyncState); 152 ((Task)iar).GetAwaiter().GetResult(); 153 } 154 155 #endregion 156 } 157 158 /// <summary> 159 /// Extends the base class to implement that action form of APM with one parameter 160 /// </summary> 161 public class AsyncAction<T> : AsyncWork 162 { Action(TArg obj)163 public delegate void Action<TArg>(TArg obj); 164 165 private Action<T> _action; 166 AsyncAction(bool throwing)167 public AsyncAction(bool throwing) 168 : base() 169 { 170 _action = (o) => 171 { 172 AddInput(o); 173 174 InvokeAction(throwing); 175 }; 176 } 177 178 #region APM 179 BeginInvoke(T t, AsyncCallback cb, object state)180 public IAsyncResult BeginInvoke(T t, AsyncCallback cb, object state) 181 { 182 Task task = Task.Factory.StartNew(_ => _action(t), state, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default); 183 task.ContinueWith(_ => cb(task)); 184 return task; 185 } 186 EndInvoke(IAsyncResult iar)187 public void EndInvoke(IAsyncResult iar) 188 { 189 CheckState(iar.AsyncState); 190 ((Task)iar).GetAwaiter().GetResult(); 191 } 192 193 #endregion 194 } 195 196 /// <summary> 197 /// Extends the base class to implement that action form of APM with two parameters 198 /// </summary> 199 public class AsyncAction<T1, T2> : AsyncWork 200 { 201 private Action<T1, T2> _action; 202 AsyncAction(bool throwing)203 public AsyncAction(bool throwing) 204 : base() 205 { 206 _action = (o1, o2) => 207 { 208 AddInput(o1); 209 AddInput(o2); 210 211 InvokeAction(throwing); 212 }; 213 } 214 215 #region APM 216 BeginInvoke(T1 t1, T2 t2, AsyncCallback cb, object state)217 public IAsyncResult BeginInvoke(T1 t1, T2 t2, AsyncCallback cb, object state) 218 { 219 Task task = Task.Factory.StartNew(_ => _action(t1, t2), state, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default); 220 task.ContinueWith(_ => cb(task)); 221 return task; 222 } 223 EndInvoke(IAsyncResult iar)224 public void EndInvoke(IAsyncResult iar) 225 { 226 CheckState(iar.AsyncState); 227 ((Task)iar).GetAwaiter().GetResult(); 228 } 229 230 #endregion 231 } 232 233 /// <summary> 234 /// Extends the base class to implement that action form of APM with three parameters 235 /// </summary> 236 public class AsyncAction<T1, T2, T3> : AsyncWork 237 { 238 private Action<T1, T2, T3> _action; 239 AsyncAction(bool throwing)240 public AsyncAction(bool throwing) 241 : base() 242 { 243 _action = (o1, o2, o3) => 244 { 245 AddInput(o1); 246 AddInput(o2); 247 AddInput(o3); 248 249 InvokeAction(throwing); 250 }; 251 } 252 253 #region APM 254 BeginInvoke(T1 t1, T2 t2, T3 t3, AsyncCallback cb, object state)255 public IAsyncResult BeginInvoke(T1 t1, T2 t2, T3 t3, AsyncCallback cb, object state) 256 { 257 Task task = Task.Factory.StartNew(_ => _action(t1, t2, t3), state, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default); 258 task.ContinueWith(_ => cb(task)); 259 return task; 260 } 261 EndInvoke(IAsyncResult iar)262 public void EndInvoke(IAsyncResult iar) 263 { 264 CheckState(iar.AsyncState); 265 ((Task)iar).GetAwaiter().GetResult(); 266 } 267 268 #endregion 269 } 270 271 #endregion 272 273 #region AsyncFunc 274 275 /// <summary> 276 /// Extends the base class to implement that function form of APM 277 /// </summary> 278 public class AsyncFunc : AsyncWork 279 { 280 private Func<ReadOnlyCollection<object>> _func; 281 282 // a general func to take-in inputs upfront rather than delayed until BeginInvoke 283 // for testing the overload taking IAsyncResult AsyncFunc(object[] inputs, bool throwing)284 public AsyncFunc(object[] inputs, bool throwing) 285 : base() 286 { 287 _func = () => 288 { 289 foreach (object o in inputs) 290 { 291 AddInput(o); 292 } 293 294 return InvokeFunc(throwing); 295 }; 296 } 297 AsyncFunc(bool throwing)298 public AsyncFunc(bool throwing) 299 : base() 300 { 301 _func = () => 302 { 303 return InvokeFunc(throwing); 304 }; 305 } 306 307 #region APM 308 BeginInvoke(AsyncCallback cb, object state)309 public IAsyncResult BeginInvoke(AsyncCallback cb, object state) 310 { 311 Task<ReadOnlyCollection<object>> task = Task.Factory.StartNew(_ => _func(), state, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default); 312 task.ContinueWith(_ => cb(task)); 313 return task; 314 } 315 EndInvoke(IAsyncResult iar)316 public ReadOnlyCollection<object> EndInvoke(IAsyncResult iar) 317 { 318 CheckState(iar.AsyncState); 319 return ((Task<ReadOnlyCollection<object>>)iar).GetAwaiter().GetResult(); 320 } 321 322 #endregion 323 } 324 325 /// <summary> 326 /// Extends the base class to implement that function form of APM with one parameter 327 /// </summary> 328 public class AsyncFunc<T> : AsyncWork 329 { 330 private Func<T, ReadOnlyCollection<object>> _func; 331 AsyncFunc(bool throwing)332 public AsyncFunc(bool throwing) 333 : base() 334 { 335 _func = (o) => 336 { 337 AddInput(o); 338 339 return InvokeFunc(throwing); 340 }; 341 } 342 343 #region APM 344 BeginInvoke(T t, AsyncCallback cb, object state)345 public IAsyncResult BeginInvoke(T t, AsyncCallback cb, object state) 346 { 347 Task<ReadOnlyCollection<object>> task = Task.Factory.StartNew(_ => _func(t), state, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default); 348 task.ContinueWith(_ => cb(task)); 349 return task; 350 } 351 EndInvoke(IAsyncResult iar)352 public ReadOnlyCollection<object> EndInvoke(IAsyncResult iar) 353 { 354 CheckState(iar.AsyncState); 355 return ((Task<ReadOnlyCollection<object>>)iar).GetAwaiter().GetResult(); 356 } 357 358 #endregion 359 } 360 361 /// <summary> 362 /// Extends the base class to implement that function form of APM with two parameters 363 /// </summary> 364 public class AsyncFunc<T1, T2> : AsyncWork 365 { 366 private Func<T1, T2, ReadOnlyCollection<object>> _func; 367 AsyncFunc(bool throwing)368 public AsyncFunc(bool throwing) 369 : base() 370 { 371 _func = (o1, o2) => 372 { 373 AddInput(o1); 374 AddInput(o2); 375 376 return InvokeFunc(throwing); 377 }; 378 } 379 380 #region APM 381 BeginInvoke(T1 t1, T2 t2, AsyncCallback cb, object state)382 public IAsyncResult BeginInvoke(T1 t1, T2 t2, AsyncCallback cb, object state) 383 { 384 Task<ReadOnlyCollection<object>> task = Task.Factory.StartNew(_ => _func(t1, t2), state, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default); 385 task.ContinueWith(_ => cb(task)); 386 return task; 387 } 388 EndInvoke(IAsyncResult iar)389 public ReadOnlyCollection<object> EndInvoke(IAsyncResult iar) 390 { 391 CheckState(iar.AsyncState); 392 return ((Task<ReadOnlyCollection<object>>)iar).GetAwaiter().GetResult(); 393 } 394 395 #endregion 396 } 397 398 /// <summary> 399 /// Extends the base class to implement that function form of APM with three parameters 400 /// </summary> 401 public class AsyncFunc<T1, T2, T3> : AsyncWork 402 { 403 private Func<T1, T2, T3, ReadOnlyCollection<object>> _func; 404 AsyncFunc(bool throwing)405 public AsyncFunc(bool throwing) 406 : base() 407 { 408 _func = (o1, o2, o3) => 409 { 410 AddInput(o1); 411 AddInput(o2); 412 AddInput(o3); 413 414 return InvokeFunc(throwing); 415 }; 416 } 417 418 #region APM 419 BeginInvoke(T1 t1, T2 t2, T3 t3, AsyncCallback cb, object state)420 public IAsyncResult BeginInvoke(T1 t1, T2 t2, T3 t3, AsyncCallback cb, object state) 421 { 422 Task<ReadOnlyCollection<object>> task = Task.Factory.StartNew(_ => _func(t1, t2, t3), state, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default); 423 task.ContinueWith(_ => cb(task)); 424 return task; 425 } 426 EndInvoke(IAsyncResult iar)427 public ReadOnlyCollection<object> EndInvoke(IAsyncResult iar) 428 { 429 CheckState(iar.AsyncState); 430 return ((Task<ReadOnlyCollection<object>>)iar).GetAwaiter().GetResult(); 431 } 432 433 #endregion 434 } 435 436 #endregion 437 } 438 439 440