4
4
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
5
5
//
6
6
// Test class that verifies the integration with APM (Task => APM) section 2.5.11 in the TPL spec
7
+ // "Asynchronous Programming Model", or the "Begin/End" pattern
7
8
//
8
9
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
9
10
@@ -18,101 +19,120 @@ namespace System.Threading.Tasks.Tests
18
19
/// <summary>
19
20
/// A class that implements the APM pattern to ensure that TPL can support APM patttern
20
21
/// </summary>
21
- public sealed class TaskAPMTest
22
+ public sealed class TaskAPMTests : IDisposable
22
23
{
23
24
/// <summary>
24
25
/// Used to indicate whether to test TPL's Task or Future functionality for the APM pattern
25
26
/// </summary>
26
- private readonly bool _hasReturnType ;
27
+ private bool _hasReturnType ;
27
28
28
29
/// <summary>
29
30
/// Used to synchornize between Main thread and async thread, by blocking the main thread until
30
31
/// the thread that invokes the TaskCompleted method via AsyncCallback finishes
31
32
/// </summary>
32
- private ManualResetEvent _mre ;
33
+ private ManualResetEvent _mre = new ManualResetEvent ( false ) ;
33
34
34
- private const int INTINPUT = 1000 ; // the input to the LongTask<int>.DoTask/BeginDoTask
35
35
/// <summary>
36
- /// The constant that defines the amount time to spinwait (to simulate work) in the LongTask class
36
+ /// The input value to LongTask<int>.DoTask/BeginDoTask
37
37
/// </summary>
38
- private const int LongTaskSeconds = 5 ;
38
+ private const int IntInput = 1000 ;
39
39
40
40
/// <summary>
41
- /// Ctor that reads the XML testcase and sets the boolean to indicate whether to test Task or Future
42
- /// functionality
41
+ /// The constant that defines the amount time to spinwait (to simulate work) in the LongTask class
43
42
/// </summary>
44
- /// <param name="hasReturnType"></param>
45
- public TaskAPMTest ( bool hasReturnType )
43
+ private const int LongTaskMilliseconds = 1000 ;
44
+
45
+ [ Theory ]
46
+ [ OuterLoop ]
47
+ [ InlineData ( true ) ]
48
+ [ InlineData ( false ) ]
49
+ public void WaitUntilCompleteTechnique ( bool hasReturnType )
46
50
{
47
51
_hasReturnType = hasReturnType ;
48
- _mre = new ManualResetEvent ( false ) ;
52
+
53
+ LongTask longTask ;
54
+ if ( _hasReturnType )
55
+ longTask = new LongTask < int > ( LongTaskMilliseconds ) ;
56
+ else
57
+ longTask = new LongTask ( LongTaskMilliseconds ) ;
58
+
59
+ // Prove that the Wait-until-done technique works
60
+ IAsyncResult asyncResult = longTask . BeginDoTask ( null , null ) ;
61
+ longTask . EndDoTask ( asyncResult ) ;
62
+
63
+ AssertTaskCompleted ( asyncResult ) ;
64
+ Assert . False ( asyncResult . CompletedSynchronously , "Should not have completed synchronously." ) ;
49
65
}
50
66
51
- /// <summary>
52
- /// Method that tests that the four APM patterns works
53
- /// </summary>
54
- /// <returns></returns>
55
- internal void RealRun ( )
67
+ [ Theory ]
68
+ [ OuterLoop ]
69
+ [ InlineData ( true ) ]
70
+ [ InlineData ( false ) ]
71
+ public void PollUntilCompleteTechnique ( bool hasReturnType )
56
72
{
57
- IAsyncResult ar ;
73
+ _hasReturnType = hasReturnType ;
58
74
59
- LongTask lt = null ;
75
+ LongTask longTask ;
60
76
if ( _hasReturnType )
61
- lt = new LongTask < int > ( LongTaskSeconds ) ;
77
+ longTask = new LongTask < int > ( LongTaskMilliseconds ) ;
62
78
else
63
- lt = new LongTask ( LongTaskSeconds ) ;
64
-
65
- //1. Prove that the Wait-until-done technique works
66
- ar = lt . BeginDoTask ( null , null ) ;
67
- lt . EndDoTask ( ar ) ;
68
- // verify task completed
69
- if ( ! VerifyTaskCompleted ( ar ) )
70
- Assert . True ( false , string . Format ( "Wait-until-done: Task is not completed" ) ) ;
79
+ longTask = new LongTask ( LongTaskMilliseconds ) ;
71
80
72
- Debug . WriteLine ( "Wait-until-Done -- Task completed" ) ;
73
-
74
- //2. Prove that the Polling technique works
75
- ar = lt . BeginDoTask ( null , null ) ;
76
- while ( ! ar . IsCompleted )
81
+ IAsyncResult asyncResult = longTask . BeginDoTask ( null , null ) ;
82
+ while ( ! asyncResult . IsCompleted )
77
83
{
78
- Task delay = Task . Delay ( 1000 ) ;
79
- delay . Wait ( ) ;
80
- //Thread.Sleep(1000);
84
+ Task . Delay ( 300 ) . Wait ( ) ;
81
85
}
82
- // verify task completed
83
- if ( ! VerifyTaskCompleted ( ar ) )
84
- Assert . True ( false , string . Format ( "Polling: Task is not completed" ) ) ;
85
-
86
- Debug . WriteLine ( "Polling -- Task completed" ) ;
87
86
88
- //3. Prove the AsyncWaitHandle works
89
- ar = lt . BeginDoTask ( null , null ) ;
90
- ar . AsyncWaitHandle . WaitOne ( ) ;
91
- // verify task completed
92
- if ( ! VerifyTaskCompleted ( ar ) )
93
- Assert . True ( false , string . Format ( "wait via AsyncWaitHandle: Task is not completed" ) ) ;
87
+ AssertTaskCompleted ( asyncResult ) ;
88
+ Assert . False ( asyncResult . CompletedSynchronously , "Should not have completed synchronously." ) ;
89
+ }
94
90
95
- Debug . WriteLine ( "Wait on AsyncWaitHandle -- Task completed" ) ;
91
+ [ Theory ]
92
+ [ OuterLoop ]
93
+ [ InlineData ( true ) ]
94
+ [ InlineData ( false ) ]
95
+ public void WaitOnAsyncWaitHandleTechnique ( bool hasReturnType )
96
+ {
97
+ _hasReturnType = hasReturnType ;
96
98
97
- //4. Prove that the Callback technique works
99
+ LongTask longTask ;
98
100
if ( _hasReturnType )
99
- ar = ( ( LongTask < int > ) lt ) . BeginDoTask ( INTINPUT , TaskCompleted , lt ) ;
101
+ longTask = new LongTask < int > ( LongTaskMilliseconds ) ;
100
102
else
101
- ar = lt . BeginDoTask ( TaskCompleted , lt ) ;
103
+ longTask = new LongTask ( LongTaskMilliseconds ) ;
102
104
103
- _mre . WaitOne ( ) ; //Block the main thread until async thread finishes executing the call back
104
- // verify task completed
105
- if ( ! VerifyTaskCompleted ( ar ) )
106
- Assert . True ( false , string . Format ( "Callback: Task is not completed" ) ) ;
105
+ IAsyncResult asyncResult = longTask . BeginDoTask ( null , null ) ;
106
+ asyncResult . AsyncWaitHandle . WaitOne ( ) ;
107
107
108
- Debug . WriteLine ( "Callback -- Task completed" ) ;
109
- //reaching this point means that the test didnt encounter any crashes or hangs.
110
- //So set the test as passed by returning true
111
- Assert . False ( ar . CompletedSynchronously , "Should not have completed synchronously." ) ;
108
+ AssertTaskCompleted ( asyncResult ) ;
109
+ Assert . False ( asyncResult . CompletedSynchronously , "Should not have completed synchronously." ) ;
110
+ }
112
111
112
+ [ Theory ]
113
+ [ OuterLoop ]
114
+ [ InlineData ( true ) ]
115
+ [ InlineData ( false ) ]
116
+ public void CallbackTechnique ( bool hasReturnType )
117
+ {
118
+ _hasReturnType = hasReturnType ;
113
119
114
- // Cleanup
115
- _mre . Dispose ( ) ;
120
+ LongTask longTask ;
121
+ if ( _hasReturnType )
122
+ longTask = new LongTask < int > ( LongTaskMilliseconds ) ;
123
+ else
124
+ longTask = new LongTask ( LongTaskMilliseconds ) ;
125
+
126
+ IAsyncResult asyncResult ;
127
+ if ( _hasReturnType )
128
+ asyncResult = ( ( LongTask < int > ) longTask ) . BeginDoTask ( IntInput , TaskCompleted , longTask ) ;
129
+ else
130
+ asyncResult = longTask . BeginDoTask ( TaskCompleted , longTask ) ;
131
+
132
+ _mre . WaitOne ( ) ; //Block the main thread until async thread finishes executing the call back
133
+
134
+ AssertTaskCompleted ( asyncResult ) ;
135
+ Assert . False ( asyncResult . CompletedSynchronously , "Should not have completed synchronously." ) ;
116
136
}
117
137
118
138
/// <summary>
@@ -125,8 +145,8 @@ private void TaskCompleted(IAsyncResult ar)
125
145
{
126
146
LongTask < int > lt = ( LongTask < int > ) ar . AsyncState ;
127
147
int retValue = lt . EndDoTask ( ar ) ;
128
- if ( retValue != INTINPUT )
129
- Assert . True ( false , string . Format ( "Mismatch: Return = {0} vs Expect = {1}" , retValue , INTINPUT ) ) ;
148
+ if ( retValue != IntInput )
149
+ Assert . True ( false , string . Format ( "Mismatch: Return = {0} vs Expect = {1}" , retValue , IntInput ) ) ;
130
150
}
131
151
else
132
152
{
@@ -138,33 +158,17 @@ private void TaskCompleted(IAsyncResult ar)
138
158
}
139
159
140
160
/// <summary>
141
- /// Verify the IAsyncResult represent a completed Task
161
+ /// Assert that the IAsyncResult represent a completed Task
142
162
/// </summary>
143
- /// <param name="ar"></param>
144
- /// <returns></returns>
145
- private bool VerifyTaskCompleted ( IAsyncResult ar )
146
- {
147
- return ar . IsCompleted &&
148
- ( ( Task ) ar ) . Status == TaskStatus . RanToCompletion ; // assume no exception thrown
149
- }
150
- }
151
-
152
- public static class TaskAPMTestCases
153
- {
154
- [ Fact ]
155
- [ OuterLoop ]
156
- public static void TaskAPMTest0 ( )
163
+ private void AssertTaskCompleted ( IAsyncResult ar )
157
164
{
158
- TaskAPMTest test = new TaskAPMTest ( false ) ;
159
- test . RealRun ( ) ;
165
+ Assert . True ( ar . IsCompleted ) ;
166
+ Assert . Equal ( TaskStatus . RanToCompletion , ( ( Task ) ar ) . Status ) ;
160
167
}
161
168
162
- [ Fact ]
163
- [ OuterLoop ]
164
- public static void TaskAPMTest1 ( )
169
+ public void Dispose ( )
165
170
{
166
- TaskAPMTest test = new TaskAPMTest ( true ) ;
167
- test . RealRun ( ) ;
171
+ _mre . Dispose ( ) ;
168
172
}
169
173
}
170
174
@@ -173,20 +177,19 @@ public static void TaskAPMTest1()
173
177
/// </summary>
174
178
public class LongTask
175
179
{
176
- //Used to store the amount time to perform spinWait
177
- protected readonly Int32 _ms ; // Milliseconds ;
180
+ // Amount of time to SpinWait, in milliseconds.
181
+ protected readonly Int32 _msWaitDuration ;
178
182
179
- public LongTask ( Int32 seconds )
183
+ public LongTask ( Int32 milliseconds )
180
184
{
181
- _ms = seconds * 1000 ;
185
+ _msWaitDuration = milliseconds ;
182
186
}
183
187
184
188
// Synchronous version of time-consuming method
185
189
public void DoTask ( )
186
190
{
187
191
// Simulate time-consuming task
188
- SpinWait . SpinUntil ( ( ) => false , _ms ) ;
189
- //Thread.SpinWait(_ms);
192
+ SpinWait . SpinUntil ( ( ) => false , _msWaitDuration ) ;
190
193
}
191
194
192
195
// Asynchronous version of time-consuming method (Begin part)
@@ -208,7 +211,7 @@ public IAsyncResult BeginDoTask(AsyncCallback callback, Object state)
208
211
} ) ;
209
212
}
210
213
211
- return task ; // Return the IAsyncResult to the caller
214
+ return task ; // Return the IAsyncResult to the caller
212
215
}
213
216
214
217
// Asynchronous version of time-consuming method (End part)
@@ -226,16 +229,16 @@ public void EndDoTask(IAsyncResult asyncResult)
226
229
/// </summary>
227
230
public sealed class LongTask < T > : LongTask
228
231
{
229
- public LongTask ( Int32 seconds )
230
- : base ( seconds )
232
+ public LongTask ( Int32 milliseconds )
233
+ : base ( milliseconds )
231
234
{
232
235
}
233
236
234
237
// Synchronous version of time-consuming method
235
238
public T DoTask ( T input )
236
239
{
237
- SpinWait . SpinUntil ( ( ) => false , _ms ) ; // Simulate time-consuming task
238
- return input ; // Return some result, for now, just return the input
240
+ SpinWait . SpinUntil ( ( ) => false , _msWaitDuration ) ; // Simulate time-consuming task
241
+ return input ; // Return some result, for now, just return the input
239
242
}
240
243
241
244
public IAsyncResult BeginDoTask ( T input , AsyncCallback callback , Object state )
@@ -253,7 +256,7 @@ public IAsyncResult BeginDoTask(T input, AsyncCallback callback, Object state)
253
256
callback ( task ) ;
254
257
} ) ;
255
258
256
- return task ; // Return the IAsyncResult to the caller
259
+ return task ; // Return the IAsyncResult to the caller
257
260
}
258
261
259
262
// Asynchronous version of time-consuming method (End part)
0 commit comments