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