diff --git a/Implab.Fx.Test/Implab.Fx.Test.mono.csproj b/Implab.Fx.Test/Implab.Fx.Test.mono.csproj
new file mode 100644
--- /dev/null
+++ b/Implab.Fx.Test/Implab.Fx.Test.mono.csproj
@@ -0,0 +1,80 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}
+ Library
+ Implab.Fx.Test
+ Implab.Fx.Test
+ v4.5
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;MONO
+ prompt
+ 4
+ false
+
+
+ true
+ bin\Release
+ prompt
+ 4
+ false
+ MONO
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;TRACE;NET_4_5;MONO
+ prompt
+ 4
+ false
+
+
+ true
+ bin\Release
+ NET_4_5;MONO
+ prompt
+ 4
+ false
+
+
+
+
+
+
+
+
+
+
+
+ {06E706F8-6881-43EB-927E-FFC503AF6ABC}
+ Implab.Fx
+
+
+ {F550F1F8-8746-4AD0-9614-855F4C4B7F05}
+ Implab
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Implab.Fx.Test/OverlayTest.cs b/Implab.Fx.Test/OverlayTest.cs
--- a/Implab.Fx.Test/OverlayTest.cs
+++ b/Implab.Fx.Test/OverlayTest.cs
@@ -1,12 +1,18 @@
-using System;
-using System.Text;
-using System.Collections.Generic;
-using System.Linq;
+using System.Windows.Forms;
+using Implab.Fx.Test.Sample;
+using Implab.Fx;
+
+#if MONO
+
+using NUnit.Framework;
+using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
+using TestMethod = NUnit.Framework.TestAttribute;
+
+#else
+
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System.Windows.Forms;
-using Implab.Fx.Test.Sample;
-using System.Drawing;
-using Implab.Fx;
+
+#endif
namespace Implab.Fx.Test
{
@@ -22,10 +28,7 @@ namespace Implab.Fx.Test
{
var overlay = new OverlayForm();
mainForm.OverlayFadeIn(overlay).Then(
- o => o.ButtonEvent += (s2, args2) =>
- {
- o.CloseFadeOut();
- }
+ o => o.ButtonEvent += (s2, args2) => o.CloseFadeOut()
);
};
diff --git a/Implab.Test/AsyncTests.cs b/Implab.Test/AsyncTests.cs
--- a/Implab.Test/AsyncTests.cs
+++ b/Implab.Test/AsyncTests.cs
@@ -1,423 +1,434 @@
-using System;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System.Reflection;
-using System.Threading;
-using Implab.Parallels;
-
-namespace Implab.Test {
- [TestClass]
- public class AsyncTests {
- [TestMethod]
- public void ResolveTest() {
- int res = -1;
- var p = new Promise();
- p.Then(x => res = x);
- p.Resolve(100);
-
- Assert.AreEqual(100, res);
- }
-
- [TestMethod]
- public void RejectTest() {
- int res = -1;
- Exception err = null;
-
- var p = new Promise();
- p.Then(
- x => res = x,
- e => {
- err = e;
- return -2;
- }
- );
- p.Reject(new ApplicationException("error"));
-
- Assert.AreEqual(res, -1);
- Assert.AreEqual(err.Message, "error");
-
- }
-
- [TestMethod]
- public void CancelExceptionTest() {
- var p = new Promise();
- p.Cancel();
-
- var p2 = p.Cancelled(() => {
- throw new ApplicationException("CANCELLED");
- });
-
- try {
- p2.Join();
- Assert.Fail();
- } catch (ApplicationException err) {
- Assert.AreEqual("CANCELLED", err.InnerException.Message);
- }
-
- }
-
- [TestMethod]
- public void ContinueOnCancelTest() {
- var p = new Promise();
- p.Cancel();
-
- var p2 = p
- .Cancelled(() => {
- throw new ApplicationException("CANCELLED");
- })
- .Error(e => true);
-
- Assert.AreEqual(true, p2.Join());
- }
-
- [TestMethod]
- public void JoinSuccessTest() {
- var p = new Promise();
- p.Resolve(100);
- Assert.AreEqual(p.Join(), 100);
- }
-
- [TestMethod]
- public void JoinFailTest() {
- var p = new Promise();
- p.Reject(new ApplicationException("failed"));
-
- try {
- p.Join();
- throw new ApplicationException("WRONG!");
- } catch (TargetInvocationException err) {
- Assert.AreEqual(err.InnerException.Message, "failed");
- } catch {
- Assert.Fail("Got wrong excaption");
- }
- }
-
- [TestMethod]
- public void MapTest() {
- var p = new Promise();
-
- var p2 = p.Then(x => x.ToString());
- p.Resolve(100);
-
- Assert.AreEqual(p2.Join(), "100");
- }
-
- [TestMethod]
- public void FixErrorTest() {
- var p = new Promise();
-
- var p2 = p.Error(e => 101);
-
- p.Reject(new Exception());
-
- Assert.AreEqual(p2.Join(), 101);
- }
-
- [TestMethod]
- public void ChainTest() {
- var p1 = new Promise();
-
- var p3 = p1.Chain(x => {
- var p2 = new Promise();
- p2.Resolve(x.ToString());
- return p2;
- });
-
- p1.Resolve(100);
-
- Assert.AreEqual(p3.Join(), "100");
- }
-
- [TestMethod]
- public void PoolTest() {
- var pid = Thread.CurrentThread.ManagedThreadId;
- var p = AsyncPool.Invoke(() => Thread.CurrentThread.ManagedThreadId);
-
- Assert.AreNotEqual(pid, p.Join());
- }
-
- [TestMethod]
- public void WorkerPoolSizeTest() {
- var pool = new WorkerPool(5, 10, 0);
-
- Assert.AreEqual(5, pool.PoolSize);
-
- pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
- pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
- pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
-
- Assert.AreEqual(5, pool.PoolSize);
-
- for (int i = 0; i < 100; i++)
- pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
- Thread.Sleep(200);
- Assert.AreEqual(10, pool.PoolSize);
-
- pool.Dispose();
- }
-
- [TestMethod]
- public void WorkerPoolCorrectTest() {
- var pool = new WorkerPool(0,1000,100);
-
- int iterations = 1000;
- int pending = iterations;
- var stop = new ManualResetEvent(false);
-
- var count = 0;
- for (int i = 0; i < iterations; i++) {
- pool
- .Invoke(() => 1)
- .Then(x => Interlocked.Add(ref count, x))
- .Then(x => Math.Log10(x))
- .Anyway(() => {
- Interlocked.Decrement(ref pending);
- if (pending == 0)
- stop.Set();
- });
- }
-
- stop.WaitOne();
-
- Assert.AreEqual(iterations, count);
- Console.WriteLine("Max threads: {0}", pool.MaxRunningThreads);
- pool.Dispose();
-
- }
-
- [TestMethod]
- public void WorkerPoolDisposeTest() {
- var pool = new WorkerPool(5, 20);
- Assert.AreEqual(5, pool.PoolSize);
- pool.Dispose();
- Thread.Sleep(500);
- Assert.AreEqual(0, pool.PoolSize);
- pool.Dispose();
- }
-
- [TestMethod]
- public void MTQueueTest() {
- var queue = new MTQueue();
- int res;
-
- queue.Enqueue(10);
- Assert.IsTrue(queue.TryDequeue(out res));
- Assert.AreEqual(10, res);
- Assert.IsFalse(queue.TryDequeue(out res));
-
- for (int i = 0; i < 1000; i++)
- queue.Enqueue(i);
-
- for (int i = 0; i < 1000; i++) {
- queue.TryDequeue(out res);
- Assert.AreEqual(i, res);
- }
-
- int writers = 0;
- int readers = 0;
- var stop = new ManualResetEvent(false);
- int total = 0;
-
- int itemsPerWriter = 10000;
- int writersCount = 10;
-
- for (int i = 0; i < writersCount; i++) {
- Interlocked.Increment(ref writers);
- var wn = i;
- AsyncPool
- .InvokeNewThread(() => {
- for (int ii = 0; ii < itemsPerWriter; ii++) {
- queue.Enqueue(1);
- }
- return 1;
- })
- .Anyway(() => Interlocked.Decrement(ref writers));
- }
-
- for (int i = 0; i < 10; i++) {
- Interlocked.Increment(ref readers);
- var wn = i;
- AsyncPool
- .InvokeNewThread(() => {
- int t;
- do {
- while (queue.TryDequeue(out t))
- Interlocked.Add(ref total, t);
- } while (writers > 0);
- return 1;
- })
- .Anyway(() => {
- Interlocked.Decrement(ref readers);
- if (readers == 0)
- stop.Set();
- });
- }
-
- stop.WaitOne();
-
- Assert.AreEqual(itemsPerWriter * writersCount, total);
- }
-
- [TestMethod]
- public void ParallelMapTest() {
-
- int count = 100000;
-
- double[] args = new double[count];
- var rand = new Random();
-
- for (int i = 0; i < count; i++)
- args[i] = rand.NextDouble();
-
- var t = Environment.TickCount;
- var res = args.ParallelMap(x => Math.Sin(x*x), 4).Join();
-
- Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
-
- t = Environment.TickCount;
- for (int i = 0; i < count; i++)
- Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
- Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
- }
-
- [TestMethod]
- public void ChainedMapTest() {
-
- using (var pool = new WorkerPool(0,100,100)) {
- int count = 10000;
-
- double[] args = new double[count];
- var rand = new Random();
-
- for (int i = 0; i < count; i++)
- args[i] = rand.NextDouble();
-
- var t = Environment.TickCount;
- var res = args
- .ChainedMap(
- x => pool.Invoke(
- () => Math.Sin(x * x)
- ),
- 4
- )
- .Join();
-
- Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
-
- t = Environment.TickCount;
- for (int i = 0; i < count; i++)
- Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
- Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
- Console.WriteLine("Max workers: {0}", pool.MaxRunningThreads);
- }
- }
-
- [TestMethod]
- public void ParallelForEachTest() {
-
- int count = 100000;
-
- int[] args = new int[count];
- var rand = new Random();
-
- for (int i = 0; i < count; i++)
- args[i] = (int)(rand.NextDouble() * 100);
-
- int result = 0;
-
- var t = Environment.TickCount;
- args.ParallelForEach(x => Interlocked.Add(ref result, x), 4).Join();
-
- Console.WriteLine("Iteration complete in {0} ms, result: {1}", Environment.TickCount - t, result);
-
- int result2 = 0;
-
- t = Environment.TickCount;
- for (int i = 0; i < count; i++)
- result2 += args[i];
- Assert.AreEqual(result2, result);
- Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
- }
-
- [TestMethod]
- public void ComplexCase1Test() {
- var flags = new bool[3];
-
- // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map)
-
- var p = PromiseHelper
- .Sleep(200, "Alan")
- .Cancelled(() => flags[0] = true)
- .Chain(x =>
- PromiseHelper
- .Sleep(200, "Hi, " + x)
- .Then(y => y)
- .Cancelled(() => flags[1] = true)
- )
- .Cancelled(() => flags[2] = true);
- Thread.Sleep(300);
- p.Cancel();
- try {
- Assert.AreEqual(p.Join(), "Hi, Alan");
- Assert.Fail("Shouldn't get here");
- } catch (OperationCanceledException) {
- }
-
- Assert.IsFalse(flags[0]);
- Assert.IsTrue(flags[1]);
- Assert.IsTrue(flags[2]);
- }
-
- [TestMethod]
- public void ChainedCancel1Test() {
- //
- // OperationCanceledException
- var p = PromiseHelper
- .Sleep(1, "Hi, HAL!")
- .Then(x => {
- //
- var result = PromiseHelper.Sleep(1000, "HEM ENABLED!!!");
- //
- PromiseHelper
- .Sleep(100, "HAL, STOP!")
- .Then(() => result.Cancel());
- return result;
- });
- try {
- p.Join();
- } catch (TargetInvocationException err) {
- Assert.IsTrue(err.InnerException is OperationCanceledException);
- }
- }
-
- [TestMethod]
- public void ChainedCancel2Test() {
- // ,
- var pSurvive = new Promise();
- var hemStarted = new ManualResetEvent(false);
- var p = PromiseHelper
- .Sleep(1, "Hi, HAL!")
- .Chain(x => {
- hemStarted.Set();
- //
- var result = PromiseHelper
- .Sleep(10000, "HEM ENABLED!!!")
- .Then(s => pSurvive.Resolve(false));
-
- result
- .Cancelled(() => pSurvive.Resolve(true));
-
- return result;
- });
-
- hemStarted.WaitOne();
- p.Cancel();
-
- try {
- p.Join();
- } catch (OperationCanceledException) {
- Assert.IsTrue(pSurvive.Join());
- }
- }
- }
-}
-
+using System;
+using System.Reflection;
+using System.Threading;
+using Implab.Parallels;
+
+#if MONO
+
+using NUnit.Framework;
+using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
+using TestMethod = NUnit.Framework.TestAttribute;
+
+#else
+
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+#endif
+
+namespace Implab.Test {
+ [TestClass]
+ public class AsyncTests {
+ [TestMethod]
+ public void ResolveTest() {
+ int res = -1;
+ var p = new Promise();
+ p.Then(x => res = x);
+ p.Resolve(100);
+
+ Assert.AreEqual(100, res);
+ }
+
+ [TestMethod]
+ public void RejectTest() {
+ int res = -1;
+ Exception err = null;
+
+ var p = new Promise();
+ p.Then(
+ x => res = x,
+ e => {
+ err = e;
+ return -2;
+ }
+ );
+ p.Reject(new ApplicationException("error"));
+
+ Assert.AreEqual(res, -1);
+ Assert.AreEqual(err.Message, "error");
+
+ }
+
+ [TestMethod]
+ public void CancelExceptionTest() {
+ var p = new Promise();
+ p.Cancel();
+
+ var p2 = p.Cancelled(() => {
+ throw new ApplicationException("CANCELLED");
+ });
+
+ try {
+ p2.Join();
+ Assert.Fail();
+ } catch (ApplicationException err) {
+ Assert.AreEqual("CANCELLED", err.InnerException.Message);
+ }
+
+ }
+
+ [TestMethod]
+ public void ContinueOnCancelTest() {
+ var p = new Promise();
+ p.Cancel();
+
+ var p2 = p
+ .Cancelled(() => {
+ throw new ApplicationException("CANCELLED");
+ })
+ .Error(e => true);
+
+ Assert.AreEqual(true, p2.Join());
+ }
+
+ [TestMethod]
+ public void JoinSuccessTest() {
+ var p = new Promise();
+ p.Resolve(100);
+ Assert.AreEqual(p.Join(), 100);
+ }
+
+ [TestMethod]
+ public void JoinFailTest() {
+ var p = new Promise();
+ p.Reject(new ApplicationException("failed"));
+
+ try {
+ p.Join();
+ throw new ApplicationException("WRONG!");
+ } catch (TargetInvocationException err) {
+ Assert.AreEqual(err.InnerException.Message, "failed");
+ } catch {
+ Assert.Fail("Got wrong excaption");
+ }
+ }
+
+ [TestMethod]
+ public void MapTest() {
+ var p = new Promise();
+
+ var p2 = p.Then(x => x.ToString());
+ p.Resolve(100);
+
+ Assert.AreEqual(p2.Join(), "100");
+ }
+
+ [TestMethod]
+ public void FixErrorTest() {
+ var p = new Promise();
+
+ var p2 = p.Error(e => 101);
+
+ p.Reject(new Exception());
+
+ Assert.AreEqual(p2.Join(), 101);
+ }
+
+ [TestMethod]
+ public void ChainTest() {
+ var p1 = new Promise();
+
+ var p3 = p1.Chain(x => {
+ var p2 = new Promise();
+ p2.Resolve(x.ToString());
+ return p2;
+ });
+
+ p1.Resolve(100);
+
+ Assert.AreEqual(p3.Join(), "100");
+ }
+
+ [TestMethod]
+ public void PoolTest() {
+ var pid = Thread.CurrentThread.ManagedThreadId;
+ var p = AsyncPool.Invoke(() => Thread.CurrentThread.ManagedThreadId);
+
+ Assert.AreNotEqual(pid, p.Join());
+ }
+
+ [TestMethod]
+ public void WorkerPoolSizeTest() {
+ var pool = new WorkerPool(5, 10, 0);
+
+ Assert.AreEqual(5, pool.PoolSize);
+
+ pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
+ pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
+ pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
+
+ Assert.AreEqual(5, pool.PoolSize);
+
+ for (int i = 0; i < 100; i++)
+ pool.Invoke(() => { Thread.Sleep(100000000); return 10; });
+ Thread.Sleep(200);
+ Assert.AreEqual(10, pool.PoolSize);
+
+ pool.Dispose();
+ }
+
+ [TestMethod]
+ public void WorkerPoolCorrectTest() {
+ var pool = new WorkerPool(0,1000,100);
+
+ const int iterations = 1000;
+ int pending = iterations;
+ var stop = new ManualResetEvent(false);
+
+ var count = 0;
+ for (int i = 0; i < iterations; i++) {
+ pool
+ .Invoke(() => 1)
+ .Then(x => Interlocked.Add(ref count, x))
+ .Then(x => Math.Log10(x))
+ .Anyway(() => {
+ Interlocked.Decrement(ref pending);
+ if (pending == 0)
+ stop.Set();
+ });
+ }
+
+ stop.WaitOne();
+
+ Assert.AreEqual(iterations, count);
+ Console.WriteLine("Max threads: {0}", pool.MaxRunningThreads);
+ pool.Dispose();
+
+ }
+
+ [TestMethod]
+ public void WorkerPoolDisposeTest() {
+ var pool = new WorkerPool(5, 20);
+ Assert.AreEqual(5, pool.PoolSize);
+ pool.Dispose();
+ Thread.Sleep(500);
+ Assert.AreEqual(0, pool.PoolSize);
+ pool.Dispose();
+ }
+
+ [TestMethod]
+ public void MTQueueTest() {
+ var queue = new MTQueue();
+ int res;
+
+ queue.Enqueue(10);
+ Assert.IsTrue(queue.TryDequeue(out res));
+ Assert.AreEqual(10, res);
+ Assert.IsFalse(queue.TryDequeue(out res));
+
+ for (int i = 0; i < 1000; i++)
+ queue.Enqueue(i);
+
+ for (int i = 0; i < 1000; i++) {
+ queue.TryDequeue(out res);
+ Assert.AreEqual(i, res);
+ }
+
+ int writers = 0;
+ int readers = 0;
+ var stop = new ManualResetEvent(false);
+ int total = 0;
+
+ const int itemsPerWriter = 10000;
+ const int writersCount = 10;
+
+ for (int i = 0; i < writersCount; i++) {
+ Interlocked.Increment(ref writers);
+ AsyncPool
+ .InvokeNewThread(() => {
+ for (int ii = 0; ii < itemsPerWriter; ii++) {
+ queue.Enqueue(1);
+ }
+ return 1;
+ })
+ .Anyway(() => Interlocked.Decrement(ref writers));
+ }
+
+ for (int i = 0; i < 10; i++) {
+ Interlocked.Increment(ref readers);
+ AsyncPool
+ .InvokeNewThread(() => {
+ int t;
+ do {
+ while (queue.TryDequeue(out t))
+ Interlocked.Add(ref total, t);
+ } while (writers > 0);
+ return 1;
+ })
+ .Anyway(() => {
+ Interlocked.Decrement(ref readers);
+ if (readers == 0)
+ stop.Set();
+ });
+ }
+
+ stop.WaitOne();
+
+ Assert.AreEqual(itemsPerWriter * writersCount, total);
+ }
+
+ [TestMethod]
+ public void ParallelMapTest() {
+
+ const int count = 100000;
+
+ var args = new double[count];
+ var rand = new Random();
+
+ for (int i = 0; i < count; i++)
+ args[i] = rand.NextDouble();
+
+ var t = Environment.TickCount;
+ var res = args.ParallelMap(x => Math.Sin(x*x), 4).Join();
+
+ Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
+
+ t = Environment.TickCount;
+ for (int i = 0; i < count; i++)
+ Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
+ Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
+ }
+
+ [TestMethod]
+ public void ChainedMapTest() {
+
+ using (var pool = new WorkerPool(0,100,100)) {
+ const int count = 10000;
+
+ var args = new double[count];
+ var rand = new Random();
+
+ for (int i = 0; i < count; i++)
+ args[i] = rand.NextDouble();
+
+ var t = Environment.TickCount;
+ var res = args
+ .ChainedMap(
+ // Analysis disable once AccessToDisposedClosure
+ x => pool.Invoke(
+ () => Math.Sin(x * x)
+ ),
+ 4
+ )
+ .Join();
+
+ Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t);
+
+ t = Environment.TickCount;
+ for (int i = 0; i < count; i++)
+ Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]);
+ Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
+ Console.WriteLine("Max workers: {0}", pool.MaxRunningThreads);
+ }
+ }
+
+ [TestMethod]
+ public void ParallelForEachTest() {
+
+ const int count = 100000;
+
+ var args = new int[count];
+ var rand = new Random();
+
+ for (int i = 0; i < count; i++)
+ args[i] = (int)(rand.NextDouble() * 100);
+
+ int result = 0;
+
+ var t = Environment.TickCount;
+ args.ParallelForEach(x => Interlocked.Add(ref result, x), 4).Join();
+
+ Console.WriteLine("Iteration complete in {0} ms, result: {1}", Environment.TickCount - t, result);
+
+ int result2 = 0;
+
+ t = Environment.TickCount;
+ for (int i = 0; i < count; i++)
+ result2 += args[i];
+ Assert.AreEqual(result2, result);
+ Console.WriteLine("Verified in {0} ms", Environment.TickCount - t);
+ }
+
+ [TestMethod]
+ public void ComplexCase1Test() {
+ var flags = new bool[3];
+
+ // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map)
+
+ var step1 = PromiseHelper
+ .Sleep(200, "Alan")
+ .Cancelled(() => flags[0] = true);
+ var p = step1
+ .Chain(x =>
+ PromiseHelper
+ .Sleep(200, "Hi, " + x)
+ .Then(y => y)
+ .Cancelled(() => flags[1] = true)
+ )
+ .Cancelled(() => flags[2] = true);
+ step1.Join();
+ p.Cancel();
+ try {
+ Assert.AreEqual(p.Join(), "Hi, Alan");
+ Assert.Fail("Shouldn't get here");
+ } catch (OperationCanceledException) {
+ }
+
+ Assert.IsFalse(flags[0]);
+ Assert.IsTrue(flags[1]);
+ Assert.IsTrue(flags[2]);
+ }
+
+ [TestMethod]
+ public void ChainedCancel1Test() {
+ // при отмене сцепленной асинхронной операции все обещание должно
+ // завершаться ошибкой OperationCanceledException
+ var p = PromiseHelper
+ .Sleep(1, "Hi, HAL!")
+ .Then(x => {
+ // запускаем две асинхронные операции
+ var result = PromiseHelper.Sleep(1000, "HEM ENABLED!!!");
+ // вторая операция отменяет первую до завершения
+ PromiseHelper
+ .Sleep(100, "HAL, STOP!")
+ .Then(result.Cancel);
+ return result;
+ });
+ try {
+ p.Join();
+ } catch (TargetInvocationException err) {
+ Assert.IsTrue(err.InnerException is OperationCanceledException);
+ }
+ }
+
+ [TestMethod]
+ public void ChainedCancel2Test() {
+ // при отмене цепочки обещаний, вложенные операции также должны отменяться
+ var pSurvive = new Promise();
+ var hemStarted = new ManualResetEvent(false);
+ var p = PromiseHelper
+ .Sleep(1, "Hi, HAL!")
+ .Chain(x => {
+ hemStarted.Set();
+ // запускаем две асинхронные операции
+ var result = PromiseHelper
+ .Sleep(10000, "HEM ENABLED!!!")
+ .Then(s => pSurvive.Resolve(false));
+
+ result
+ .Cancelled(() => pSurvive.Resolve(true));
+
+ return result;
+ });
+
+ hemStarted.WaitOne();
+ p.Cancel();
+
+ try {
+ p.Join();
+ } catch (OperationCanceledException) {
+ Assert.IsTrue(pSurvive.Join());
+ }
+ }
+ }
+}
+
diff --git a/Implab.Test/Implab.Test.mono.csproj b/Implab.Test/Implab.Test.mono.csproj
new file mode 100644
--- /dev/null
+++ b/Implab.Test/Implab.Test.mono.csproj
@@ -0,0 +1,66 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}
+ Library
+ Implab.Test
+ Implab.Test
+ v4.5
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;MONO
+ prompt
+ 4
+ false
+
+
+ true
+ bin\Release
+ prompt
+ 4
+ false
+ MONO
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;TRACE;NET_4_5;MONO
+ prompt
+ 4
+ false
+
+
+ true
+ bin\Release
+ NET_4_5;MONO
+ prompt
+ 4
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {F550F1F8-8746-4AD0-9614-855F4C4B7F05}
+ Implab
+
+
+
\ No newline at end of file
diff --git a/Implab.Test/PromiseHelper.cs b/Implab.Test/PromiseHelper.cs
--- a/Implab.Test/PromiseHelper.cs
+++ b/Implab.Test/PromiseHelper.cs
@@ -1,12 +1,8 @@
using Implab.Parallels;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using System.Threading;
namespace Implab.Test {
- class PromiseHelper {
+ static class PromiseHelper {
public static IPromise Sleep(int timeout, T retVal) {
return AsyncPool.Invoke(() => {
Thread.Sleep(timeout);
diff --git a/Implab.Test/Properties/AssemblyInfo.cs b/Implab.Test/Properties/AssemblyInfo.cs
--- a/Implab.Test/Properties/AssemblyInfo.cs
+++ b/Implab.Test/Properties/AssemblyInfo.cs
@@ -31,5 +31,4 @@ using System.Runtime.InteropServices;
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: AssemblyVersion("0.0.*")]
diff --git a/Implab.mono.sln b/Implab.mono.sln
new file mode 100644
--- /dev/null
+++ b/Implab.mono.sln
@@ -0,0 +1,290 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab", "Implab\Implab.csproj", "{F550F1F8-8746-4AD0-9614-855F4C4B7F05}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CE8D8D18-437A-445C-B662-4C2CE79A76F6}"
+ ProjectSection(SolutionItems) = preProject
+ Implab.vsmdi = Implab.vsmdi
+ Local.testsettings = Local.testsettings
+ TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Fx", "Implab.Fx\Implab.Fx.csproj", "{06E706F8-6881-43EB-927E-FFC503AF6ABC}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{BCA337C3-BFDC-4825-BBDB-E6D467E4E452}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Test.mono", "Implab.Test\Implab.Test.mono.csproj", "{2BD05F84-E067-4B87-9477-FDC2676A21C6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Fx.Test.mono", "Implab.Fx.Test\Implab.Fx.Test.mono.csproj", "{2BD05F84-E067-4B87-9477-FDC2676A21C6}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ Debug 4.5|Any CPU = Debug 4.5|Any CPU
+ Release 4.5|Any CPU = Release 4.5|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
+ {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
+ {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
+ {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
+ {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2F31E405-E267-4195-A05D-574093C21209}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
+ {2F31E405-E267-4195-A05D-574093C21209}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
+ {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F31E405-E267-4195-A05D-574093C21209}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
+ {2F31E405-E267-4195-A05D-574093C21209}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
+ {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.Build.0 = Release|Any CPU
+ {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
+ {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
+ {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
+ {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
+ {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
+ {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
+ {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
+ {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
+ {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6} = {BCA337C3-BFDC-4825-BBDB-E6D467E4E452}
+ {2BD05F84-E067-4B87-9477-FDC2676A21C6} = {BCA337C3-BFDC-4825-BBDB-E6D467E4E452}
+ EndGlobalSection
+ GlobalSection(MonoDevelopProperties) = preSolution
+ StartupItem = Implab\Implab.csproj
+ Policies = $0
+ $0.CSharpFormattingPolicy = $1
+ $1.IndentSwitchBody = True
+ $1.NamespaceBraceStyle = EndOfLine
+ $1.ClassBraceStyle = EndOfLine
+ $1.InterfaceBraceStyle = EndOfLine
+ $1.StructBraceStyle = EndOfLine
+ $1.EnumBraceStyle = EndOfLine
+ $1.MethodBraceStyle = EndOfLine
+ $1.ConstructorBraceStyle = EndOfLine
+ $1.DestructorBraceStyle = EndOfLine
+ $1.BeforeMethodDeclarationParentheses = False
+ $1.BeforeMethodCallParentheses = False
+ $1.BeforeConstructorDeclarationParentheses = False
+ $1.NewLineBeforeConstructorInitializerColon = NewLine
+ $1.NewLineAfterConstructorInitializerColon = SameLine
+ $1.BeforeIndexerDeclarationBracket = False
+ $1.BeforeDelegateDeclarationParentheses = False
+ $1.NewParentheses = False
+ $1.SpacesBeforeBrackets = False
+ $1.inheritsSet = Mono
+ $1.inheritsScope = text/x-csharp
+ $1.scope = text/x-csharp
+ $0.TextStylePolicy = $2
+ $2.FileWidth = 120
+ $2.EolMarker = Unix
+ $2.inheritsSet = VisualStudio
+ $2.inheritsScope = text/plain
+ $2.scope = text/x-csharp
+ $0.DotNetNamingPolicy = $3
+ $3.DirectoryNamespaceAssociation = PrefixedHierarchical
+ $3.ResourceNamePolicy = MSBuild
+ $0.TextStylePolicy = $4
+ $4.FileWidth = 120
+ $4.TabsToSpaces = False
+ $4.inheritsSet = VisualStudio
+ $4.inheritsScope = text/plain
+ $4.scope = application/xml
+ $0.XmlFormattingPolicy = $5
+ $5.inheritsSet = Mono
+ $5.inheritsScope = application/xml
+ $5.scope = application/xml
+ $0.TextStylePolicy = $6
+ $6.FileWidth = 120
+ $6.TabsToSpaces = False
+ $6.inheritsSet = VisualStudio
+ $6.inheritsScope = text/plain
+ $6.scope = text/plain
+ $0.NameConventionPolicy = $7
+ $7.Rules = $8
+ $8.NamingRule = $9
+ $9.Name = Namespaces
+ $9.AffectedEntity = Namespace
+ $9.VisibilityMask = VisibilityMask
+ $9.NamingStyle = PascalCase
+ $9.IncludeInstanceMembers = True
+ $9.IncludeStaticEntities = True
+ $8.NamingRule = $10
+ $10.Name = Types
+ $10.AffectedEntity = Class, Struct, Enum, Delegate
+ $10.VisibilityMask = VisibilityMask
+ $10.NamingStyle = PascalCase
+ $10.IncludeInstanceMembers = True
+ $10.IncludeStaticEntities = True
+ $8.NamingRule = $11
+ $11.Name = Interfaces
+ $11.RequiredPrefixes = $12
+ $12.String = I
+ $11.AffectedEntity = Interface
+ $11.VisibilityMask = VisibilityMask
+ $11.NamingStyle = PascalCase
+ $11.IncludeInstanceMembers = True
+ $11.IncludeStaticEntities = True
+ $8.NamingRule = $13
+ $13.Name = Attributes
+ $13.RequiredSuffixes = $14
+ $14.String = Attribute
+ $13.AffectedEntity = CustomAttributes
+ $13.VisibilityMask = VisibilityMask
+ $13.NamingStyle = PascalCase
+ $13.IncludeInstanceMembers = True
+ $13.IncludeStaticEntities = True
+ $8.NamingRule = $15
+ $15.Name = Event Arguments
+ $15.RequiredSuffixes = $16
+ $16.String = EventArgs
+ $15.AffectedEntity = CustomEventArgs
+ $15.VisibilityMask = VisibilityMask
+ $15.NamingStyle = PascalCase
+ $15.IncludeInstanceMembers = True
+ $15.IncludeStaticEntities = True
+ $8.NamingRule = $17
+ $17.Name = Exceptions
+ $17.RequiredSuffixes = $18
+ $18.String = Exception
+ $17.AffectedEntity = CustomExceptions
+ $17.VisibilityMask = VisibilityMask
+ $17.NamingStyle = PascalCase
+ $17.IncludeInstanceMembers = True
+ $17.IncludeStaticEntities = True
+ $8.NamingRule = $19
+ $19.Name = Methods
+ $19.AffectedEntity = Methods
+ $19.VisibilityMask = VisibilityMask
+ $19.NamingStyle = PascalCase
+ $19.IncludeInstanceMembers = True
+ $19.IncludeStaticEntities = True
+ $8.NamingRule = $20
+ $20.Name = Static Readonly Fields
+ $20.AffectedEntity = ReadonlyField
+ $20.VisibilityMask = Internal, Protected, Public
+ $20.NamingStyle = PascalCase
+ $20.IncludeInstanceMembers = False
+ $20.IncludeStaticEntities = True
+ $8.NamingRule = $21
+ $21.Name = Fields (Non Private)
+ $21.AffectedEntity = Field
+ $21.VisibilityMask = Internal, Public
+ $21.NamingStyle = CamelCase
+ $21.IncludeInstanceMembers = True
+ $21.IncludeStaticEntities = True
+ $8.NamingRule = $22
+ $22.Name = ReadOnly Fields (Non Private)
+ $22.AffectedEntity = ReadonlyField
+ $22.VisibilityMask = Internal, Public
+ $22.NamingStyle = CamelCase
+ $22.IncludeInstanceMembers = True
+ $22.IncludeStaticEntities = False
+ $8.NamingRule = $23
+ $23.Name = Fields (Private)
+ $23.RequiredPrefixes = $24
+ $24.String = m_
+ $23.AffectedEntity = Field, ReadonlyField
+ $23.VisibilityMask = Private, Protected
+ $23.NamingStyle = CamelCase
+ $23.IncludeInstanceMembers = True
+ $23.IncludeStaticEntities = False
+ $8.NamingRule = $25
+ $25.Name = Static Fields (Private)
+ $25.RequiredPrefixes = $26
+ $26.String = _
+ $25.AffectedEntity = Field
+ $25.VisibilityMask = Private
+ $25.NamingStyle = CamelCase
+ $25.IncludeInstanceMembers = False
+ $25.IncludeStaticEntities = True
+ $8.NamingRule = $27
+ $27.Name = ReadOnly Fields (Private)
+ $27.RequiredPrefixes = $28
+ $28.String = m_
+ $27.AffectedEntity = ReadonlyField
+ $27.VisibilityMask = Private, Protected
+ $27.NamingStyle = CamelCase
+ $27.IncludeInstanceMembers = True
+ $27.IncludeStaticEntities = False
+ $8.NamingRule = $29
+ $29.Name = Constant Fields
+ $29.AffectedEntity = ConstantField
+ $29.VisibilityMask = VisibilityMask
+ $29.NamingStyle = AllUpper
+ $29.IncludeInstanceMembers = True
+ $29.IncludeStaticEntities = True
+ $8.NamingRule = $30
+ $30.Name = Properties
+ $30.AffectedEntity = Property
+ $30.VisibilityMask = VisibilityMask
+ $30.NamingStyle = PascalCase
+ $30.IncludeInstanceMembers = True
+ $30.IncludeStaticEntities = True
+ $8.NamingRule = $31
+ $31.Name = Events
+ $31.AffectedEntity = Event
+ $31.VisibilityMask = VisibilityMask
+ $31.NamingStyle = PascalCase
+ $31.IncludeInstanceMembers = True
+ $31.IncludeStaticEntities = True
+ $8.NamingRule = $32
+ $32.Name = Enum Members
+ $32.AffectedEntity = EnumMember
+ $32.VisibilityMask = VisibilityMask
+ $32.NamingStyle = PascalCase
+ $32.IncludeInstanceMembers = True
+ $32.IncludeStaticEntities = True
+ $8.NamingRule = $33
+ $33.Name = Parameters
+ $33.AffectedEntity = Parameter, LocalVariable
+ $33.VisibilityMask = VisibilityMask
+ $33.NamingStyle = CamelCase
+ $33.IncludeInstanceMembers = True
+ $33.IncludeStaticEntities = True
+ $8.NamingRule = $34
+ $34.Name = Type Parameters
+ $34.RequiredPrefixes = $35
+ $35.String = T
+ $34.AffectedEntity = TypeParameter
+ $34.VisibilityMask = VisibilityMask
+ $34.NamingStyle = PascalCase
+ $34.IncludeInstanceMembers = True
+ $34.IncludeStaticEntities = True
+ EndGlobalSection
+ GlobalSection(TestCaseManagementSettings) = postSolution
+ CategoryFile = Implab.vsmdi
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal