Mercurial > pub > ImplabNet
annotate Implab.Test/AsyncTests.cs @ 120:f1b897999260 v2
improved asyncpool usability
working on batch operations on asyncqueue
author | cin |
---|---|
date | Mon, 12 Jan 2015 05:19:52 +0300 |
parents | 2573b562e328 |
children | 62d2f1e98c4e |
rev | line source |
---|---|
77 | 1 using System; |
2 using System.Reflection; | |
3 using System.Threading; | |
4 using Implab.Parallels; | |
5 | |
6 #if MONO | |
7 | |
8 using NUnit.Framework; | |
9 using TestClassAttribute = NUnit.Framework.TestFixtureAttribute; | |
10 using TestMethod = NUnit.Framework.TestAttribute; | |
11 | |
12 #else | |
13 | |
14 using Microsoft.VisualStudio.TestTools.UnitTesting; | |
15 | |
16 #endif | |
17 | |
18 namespace Implab.Test { | |
19 [TestClass] | |
20 public class AsyncTests { | |
21 [TestMethod] | |
22 public void ResolveTest() { | |
23 int res = -1; | |
24 var p = new Promise<int>(); | |
25 p.Then(x => res = x); | |
26 p.Resolve(100); | |
27 | |
28 Assert.AreEqual(100, res); | |
29 } | |
30 | |
31 [TestMethod] | |
32 public void RejectTest() { | |
33 int res = -1; | |
34 Exception err = null; | |
35 | |
36 var p = new Promise<int>(); | |
37 p.Then( | |
38 x => res = x, | |
39 e => { | |
40 err = e; | |
41 return -2; | |
42 } | |
43 ); | |
44 p.Reject(new ApplicationException("error")); | |
45 | |
46 Assert.AreEqual(res, -1); | |
47 Assert.AreEqual(err.Message, "error"); | |
48 | |
49 } | |
50 | |
51 [TestMethod] | |
52 public void CancelExceptionTest() { | |
53 var p = new Promise<bool>(); | |
54 p.Cancel(); | |
55 | |
56 var p2 = p.Cancelled(() => { | |
57 throw new ApplicationException("CANCELLED"); | |
58 }); | |
59 | |
60 try { | |
61 p2.Join(); | |
62 Assert.Fail(); | |
63 } catch (ApplicationException err) { | |
64 Assert.AreEqual("CANCELLED", err.InnerException.Message); | |
65 } | |
66 | |
67 } | |
68 | |
69 [TestMethod] | |
70 public void ContinueOnCancelTest() { | |
71 var p = new Promise<bool>(); | |
72 p.Cancel(); | |
73 | |
74 var p2 = p | |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
75 .Cancelled<bool>(() => { |
77 | 76 throw new ApplicationException("CANCELLED"); |
77 }) | |
78 .Error(e => true); | |
79 | |
80 Assert.AreEqual(true, p2.Join()); | |
81 } | |
82 | |
83 [TestMethod] | |
84 public void JoinSuccessTest() { | |
85 var p = new Promise<int>(); | |
86 p.Resolve(100); | |
87 Assert.AreEqual(p.Join(), 100); | |
88 } | |
89 | |
90 [TestMethod] | |
91 public void JoinFailTest() { | |
92 var p = new Promise<int>(); | |
93 p.Reject(new ApplicationException("failed")); | |
94 | |
95 try { | |
96 p.Join(); | |
97 throw new ApplicationException("WRONG!"); | |
98 } catch (TargetInvocationException err) { | |
99 Assert.AreEqual(err.InnerException.Message, "failed"); | |
100 } catch { | |
101 Assert.Fail("Got wrong excaption"); | |
102 } | |
103 } | |
104 | |
105 [TestMethod] | |
106 public void MapTest() { | |
107 var p = new Promise<int>(); | |
108 | |
109 var p2 = p.Then(x => x.ToString()); | |
110 p.Resolve(100); | |
111 | |
112 Assert.AreEqual(p2.Join(), "100"); | |
113 } | |
114 | |
115 [TestMethod] | |
116 public void FixErrorTest() { | |
117 var p = new Promise<int>(); | |
118 | |
119 var p2 = p.Error(e => 101); | |
120 | |
121 p.Reject(new Exception()); | |
122 | |
123 Assert.AreEqual(p2.Join(), 101); | |
124 } | |
125 | |
126 [TestMethod] | |
127 public void ChainTest() { | |
128 var p1 = new Promise<int>(); | |
129 | |
130 var p3 = p1.Chain(x => { | |
131 var p2 = new Promise<string>(); | |
132 p2.Resolve(x.ToString()); | |
133 return p2; | |
134 }); | |
135 | |
136 p1.Resolve(100); | |
137 | |
138 Assert.AreEqual(p3.Join(), "100"); | |
139 } | |
140 | |
141 [TestMethod] | |
105 | 142 public void ChainFailTest() { |
143 var p1 = new Promise<int>(); | |
144 | |
145 var p3 = p1.Chain(x => { | |
146 var p2 = new Promise<string>(); | |
147 p2.Reject(new Exception("DIE!!!")); | |
148 return p2; | |
149 }); | |
150 | |
151 p1.Resolve(100); | |
152 | |
153 Assert.IsTrue(p3.IsResolved); | |
154 } | |
155 | |
156 [TestMethod] | |
77 | 157 public void PoolTest() { |
158 var pid = Thread.CurrentThread.ManagedThreadId; | |
159 var p = AsyncPool.Invoke(() => Thread.CurrentThread.ManagedThreadId); | |
160 | |
161 Assert.AreNotEqual(pid, p.Join()); | |
162 } | |
163 | |
164 [TestMethod] | |
165 public void WorkerPoolSizeTest() { | |
81 | 166 var pool = new WorkerPool(5, 10, 1); |
77 | 167 |
168 Assert.AreEqual(5, pool.PoolSize); | |
169 | |
170 pool.Invoke(() => { Thread.Sleep(100000000); return 10; }); | |
171 pool.Invoke(() => { Thread.Sleep(100000000); return 10; }); | |
172 pool.Invoke(() => { Thread.Sleep(100000000); return 10; }); | |
173 | |
174 Assert.AreEqual(5, pool.PoolSize); | |
175 | |
176 for (int i = 0; i < 100; i++) | |
177 pool.Invoke(() => { Thread.Sleep(100000000); return 10; }); | |
178 Thread.Sleep(200); | |
179 Assert.AreEqual(10, pool.PoolSize); | |
180 | |
181 pool.Dispose(); | |
182 } | |
183 | |
184 [TestMethod] | |
185 public void WorkerPoolCorrectTest() { | |
186 var pool = new WorkerPool(0,1000,100); | |
187 | |
188 const int iterations = 1000; | |
189 int pending = iterations; | |
190 var stop = new ManualResetEvent(false); | |
191 | |
192 var count = 0; | |
193 for (int i = 0; i < iterations; i++) { | |
194 pool | |
195 .Invoke(() => 1) | |
196 .Then(x => Interlocked.Add(ref count, x)) | |
197 .Then(x => Math.Log10(x)) | |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
198 .On(() => { |
77 | 199 Interlocked.Decrement(ref pending); |
200 if (pending == 0) | |
201 stop.Set(); | |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
202 }, PromiseEventType.All); |
77 | 203 } |
204 | |
205 stop.WaitOne(); | |
206 | |
207 Assert.AreEqual(iterations, count); | |
208 Console.WriteLine("Max threads: {0}", pool.MaxRunningThreads); | |
209 pool.Dispose(); | |
210 | |
211 } | |
212 | |
213 [TestMethod] | |
214 public void WorkerPoolDisposeTest() { | |
215 var pool = new WorkerPool(5, 20); | |
216 Assert.AreEqual(5, pool.PoolSize); | |
217 pool.Dispose(); | |
218 Thread.Sleep(500); | |
219 Assert.AreEqual(0, pool.PoolSize); | |
220 pool.Dispose(); | |
221 } | |
222 | |
223 [TestMethod] | |
224 public void MTQueueTest() { | |
225 var queue = new MTQueue<int>(); | |
226 int res; | |
227 | |
228 queue.Enqueue(10); | |
229 Assert.IsTrue(queue.TryDequeue(out res)); | |
230 Assert.AreEqual(10, res); | |
231 Assert.IsFalse(queue.TryDequeue(out res)); | |
232 | |
233 for (int i = 0; i < 1000; i++) | |
234 queue.Enqueue(i); | |
235 | |
236 for (int i = 0; i < 1000; i++) { | |
237 queue.TryDequeue(out res); | |
238 Assert.AreEqual(i, res); | |
239 } | |
240 | |
241 int writers = 0; | |
242 int readers = 0; | |
243 var stop = new ManualResetEvent(false); | |
244 int total = 0; | |
245 | |
246 const int itemsPerWriter = 10000; | |
247 const int writersCount = 10; | |
248 | |
249 for (int i = 0; i < writersCount; i++) { | |
250 Interlocked.Increment(ref writers); | |
251 AsyncPool | |
252 .InvokeNewThread(() => { | |
253 for (int ii = 0; ii < itemsPerWriter; ii++) { | |
254 queue.Enqueue(1); | |
255 } | |
256 return 1; | |
257 }) | |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
258 .On(() => Interlocked.Decrement(ref writers), PromiseEventType.All); |
77 | 259 } |
260 | |
261 for (int i = 0; i < 10; i++) { | |
262 Interlocked.Increment(ref readers); | |
263 AsyncPool | |
264 .InvokeNewThread(() => { | |
265 int t; | |
266 do { | |
267 while (queue.TryDequeue(out t)) | |
268 Interlocked.Add(ref total, t); | |
269 } while (writers > 0); | |
270 return 1; | |
271 }) | |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
272 .On(() => { |
77 | 273 Interlocked.Decrement(ref readers); |
274 if (readers == 0) | |
275 stop.Set(); | |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
276 }, PromiseEventType.All); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
277 } |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
278 |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
279 stop.WaitOne(); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
280 |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
281 Assert.AreEqual(100000, total); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
282 } |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
283 |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
284 [TestMethod] |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
285 public void AsyncQueueTest() { |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
286 var queue = new AsyncQueue<int>(); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
287 int res; |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
288 |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
289 queue.Enqueue(10); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
290 Assert.IsTrue(queue.TryDequeue(out res)); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
291 Assert.AreEqual(10, res); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
292 Assert.IsFalse(queue.TryDequeue(out res)); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
293 |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
294 for (int i = 0; i < 1000; i++) |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
295 queue.Enqueue(i); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
296 |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
297 for (int i = 0; i < 1000; i++) { |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
298 queue.TryDequeue(out res); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
299 Assert.AreEqual(i, res); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
300 } |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
301 |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
302 int writers = 0; |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
303 int readers = 0; |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
304 var stop = new ManualResetEvent(false); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
305 int total = 0; |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
306 |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
307 const int itemsPerWriter = 10000; |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
308 const int writersCount = 10; |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
309 |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
310 for (int i = 0; i < writersCount; i++) { |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
311 Interlocked.Increment(ref writers); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
312 AsyncPool |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
313 .InvokeNewThread(() => { |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
314 for (int ii = 0; ii < itemsPerWriter; ii++) { |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
315 queue.Enqueue(1); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
316 } |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
317 return 1; |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
318 }) |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
319 .On(() => Interlocked.Decrement(ref writers), PromiseEventType.All); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
320 } |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
321 |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
322 for (int i = 0; i < 10; i++) { |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
323 Interlocked.Increment(ref readers); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
324 AsyncPool |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
325 .InvokeNewThread(() => { |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
326 int t; |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
327 do { |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
328 while (queue.TryDequeue(out t)) |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
329 Interlocked.Add(ref total, t); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
330 } while (writers > 0); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
331 return 1; |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
332 }) |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
333 .On(() => { |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
334 Interlocked.Decrement(ref readers); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
335 if (readers == 0) |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
336 stop.Set(); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
337 }, PromiseEventType.All); |
77 | 338 } |
339 | |
340 stop.WaitOne(); | |
341 | |
342 Assert.AreEqual(itemsPerWriter * writersCount, total); | |
343 } | |
344 | |
345 [TestMethod] | |
346 public void ParallelMapTest() { | |
347 | |
348 const int count = 100000; | |
349 | |
350 var args = new double[count]; | |
351 var rand = new Random(); | |
352 | |
353 for (int i = 0; i < count; i++) | |
354 args[i] = rand.NextDouble(); | |
355 | |
356 var t = Environment.TickCount; | |
357 var res = args.ParallelMap(x => Math.Sin(x*x), 4).Join(); | |
358 | |
359 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t); | |
360 | |
361 t = Environment.TickCount; | |
362 for (int i = 0; i < count; i++) | |
363 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]); | |
364 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t); | |
365 } | |
366 | |
367 [TestMethod] | |
368 public void ChainedMapTest() { | |
369 | |
81 | 370 using (var pool = new WorkerPool(0,10,1)) { |
77 | 371 const int count = 10000; |
372 | |
373 var args = new double[count]; | |
374 var rand = new Random(); | |
375 | |
376 for (int i = 0; i < count; i++) | |
377 args[i] = rand.NextDouble(); | |
378 | |
379 var t = Environment.TickCount; | |
380 var res = args | |
381 .ChainedMap( | |
382 // Analysis disable once AccessToDisposedClosure | |
383 x => pool.Invoke( | |
384 () => Math.Sin(x * x) | |
385 ), | |
386 4 | |
387 ) | |
388 .Join(); | |
389 | |
390 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t); | |
391 | |
392 t = Environment.TickCount; | |
393 for (int i = 0; i < count; i++) | |
394 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]); | |
395 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t); | |
396 Console.WriteLine("Max workers: {0}", pool.MaxRunningThreads); | |
397 } | |
398 } | |
399 | |
400 [TestMethod] | |
401 public void ParallelForEachTest() { | |
402 | |
403 const int count = 100000; | |
404 | |
405 var args = new int[count]; | |
406 var rand = new Random(); | |
407 | |
408 for (int i = 0; i < count; i++) | |
409 args[i] = (int)(rand.NextDouble() * 100); | |
410 | |
411 int result = 0; | |
412 | |
413 var t = Environment.TickCount; | |
414 args.ParallelForEach(x => Interlocked.Add(ref result, x), 4).Join(); | |
415 | |
416 Console.WriteLine("Iteration complete in {0} ms, result: {1}", Environment.TickCount - t, result); | |
417 | |
418 int result2 = 0; | |
419 | |
420 t = Environment.TickCount; | |
421 for (int i = 0; i < count; i++) | |
422 result2 += args[i]; | |
423 Assert.AreEqual(result2, result); | |
424 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t); | |
425 } | |
426 | |
427 [TestMethod] | |
428 public void ComplexCase1Test() { | |
429 var flags = new bool[3]; | |
430 | |
431 // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map) | |
432 | |
433 var step1 = PromiseHelper | |
434 .Sleep(200, "Alan") | |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
435 .On(() => flags[0] = true, PromiseEventType.Cancelled); |
77 | 436 var p = step1 |
437 .Chain(x => | |
438 PromiseHelper | |
439 .Sleep(200, "Hi, " + x) | |
440 .Then(y => y) | |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
441 .On(() => flags[1] = true, PromiseEventType.Cancelled) |
77 | 442 ) |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
106
diff
changeset
|
443 .On(() => flags[2] = true, PromiseEventType.Cancelled); |
77 | 444 step1.Join(); |
445 p.Cancel(); | |
446 try { | |
447 Assert.AreEqual(p.Join(), "Hi, Alan"); | |
448 Assert.Fail("Shouldn't get here"); | |
449 } catch (OperationCanceledException) { | |
450 } | |
451 | |
452 Assert.IsFalse(flags[0]); | |
453 Assert.IsTrue(flags[1]); | |
454 Assert.IsTrue(flags[2]); | |
455 } | |
456 | |
457 [TestMethod] | |
458 public void ChainedCancel1Test() { | |
459 // при отмене сцепленной асинхронной операции все обещание должно | |
460 // завершаться ошибкой OperationCanceledException | |
461 var p = PromiseHelper | |
462 .Sleep(1, "Hi, HAL!") | |
463 .Then(x => { | |
464 // запускаем две асинхронные операции | |
465 var result = PromiseHelper.Sleep(1000, "HEM ENABLED!!!"); | |
466 // вторая операция отменяет первую до завершения | |
467 PromiseHelper | |
468 .Sleep(100, "HAL, STOP!") | |
469 .Then(result.Cancel); | |
470 return result; | |
471 }); | |
472 try { | |
473 p.Join(); | |
474 } catch (TargetInvocationException err) { | |
475 Assert.IsTrue(err.InnerException is OperationCanceledException); | |
476 } | |
477 } | |
478 | |
479 [TestMethod] | |
480 public void ChainedCancel2Test() { | |
481 // при отмене цепочки обещаний, вложенные операции также должны отменяться | |
482 var pSurvive = new Promise<bool>(); | |
483 var hemStarted = new ManualResetEvent(false); | |
484 var p = PromiseHelper | |
485 .Sleep(1, "Hi, HAL!") | |
486 .Chain(x => { | |
487 hemStarted.Set(); | |
488 // запускаем две асинхронные операции | |
489 var result = PromiseHelper | |
106 | 490 .Sleep(100000000, "HEM ENABLED!!!") |
491 .Then(s => { | |
492 pSurvive.Resolve(false); | |
493 return s; | |
494 }); | |
77 | 495 |
496 result | |
497 .Cancelled(() => pSurvive.Resolve(true)); | |
498 | |
499 return result; | |
500 }); | |
501 | |
502 hemStarted.WaitOne(); | |
503 p.Cancel(); | |
504 | |
505 try { | |
506 p.Join(); | |
507 } catch (OperationCanceledException) { | |
508 Assert.IsTrue(pSurvive.Join()); | |
509 } | |
510 } | |
511 } | |
512 } | |
513 |