public async Task TestThrottledDebounce2()
        {
            int counter = 0;
            EventHandler <int> action = (_, myIntParam) => {
                Log.d("myIntParam=" + myIntParam);
                Interlocked.Increment(ref counter);
            };
            var throttledAction = action.AsThrottledDebounce(delayInMs: 5);

            var tasks = new List <Task>();

            for (int i = 0; i < 100; i++)   // Do 100 calls of the method in parallel:
            {
                var myIntParam = i;
                tasks.Add(TaskV2.Run(() => { throttledAction(this, myIntParam); }));
            }
            await Task.WhenAll(tasks.ToArray());

            for (int i = 0; i < 20; i++)
            {
                await TaskV2.Delay(30);

                if (counter >= 2)
                {
                    break;
                }
            }
            Assert.Equal(2, counter);
            await TaskV2.Delay(100);

            Assert.Equal(2, counter);
        }
Beispiel #2
0
        private static async Task TestErrorDetectionWithMultipleThreads(Func <Task> newErrorTask)
        {
            var d = new MyDisposable();

            using (d) {
                Task t1 = TaskV2.Run(newErrorTask);
                Task t2 = null, t3 = null;
                try {
                    Assert.False(d.DEBUG_ThrownExceptionDetectedInCurrentContext());
                    t2 = TaskV2.Run(newErrorTask);
                    Assert.False(d.DEBUG_ThrownExceptionDetectedInCurrentContext());
                    t3 = TaskV2.Run(newErrorTask);
                    Assert.False(d.DEBUG_ThrownExceptionDetectedInCurrentContext());
                    await Task.WhenAll(t1, t2, t3);
                } catch (Exception) {
                    Assert.True(d.DEBUG_ThrownExceptionDetectedInCurrentContext());
                }
                Assert.False(d.DEBUG_ThrownExceptionDetectedInCurrentContext());
                Assert.True(t1.IsCompleted);
                Assert.True(t2.IsCompleted);
                Assert.True(t3.IsCompleted);
                Assert.True(t1.IsFaulted);
                Assert.True(t2.IsFaulted);
                Assert.True(t3.IsFaulted);
            }
            Assert.False(d.DEBUG_ThrownExceptionDetectedInCurrentContext());
            Assert.False(d.exceptionWasDetected);
        }
Beispiel #3
0
        public async Task ExampleUsage1()
        {
            Log.d("Now testing TaskV2.Run");
            await TaskV2.Run(() => {
                var t = Log.MethodEntered("1");
                TaskV2.Delay(100).ContinueWithSameContext(delegate {
                    Log.MethodDone(t);
                });
            });

            Log.d("Now testing async TaskV2.Run");
            await TaskV2.Run(async() => {
                var t = Log.MethodEntered("2");
                await TaskV2.Delay(100);
                Log.MethodDone(t);
            });

            Log.d("Now testing async TaskV2.Run with return value");
            var result = await TaskV2.Run(async() => {
                var t = Log.MethodEntered("3");
                await TaskV2.Delay(100);
                Log.MethodDone(t);
                return("3");
            });

            Assert.Equal("3", result);
        }
Beispiel #4
0
        public void TestTemporaryContext1()
        {
            var IoC_inject = GetInjectorForTest();

            Assert.Null(IoC_inject.Get <MyClass1>(this));
            for (int i = 0; i < 100; i++)
            {
                TaskV2.Run(() => {
                    var myContextInstance1 = new MyClass1();
                    IoC_inject.DoWithTempContext <MyClass1>(myContextInstance1, () => {
                        Assert.Equal(myContextInstance1, IoC_inject.Get <MyClass1>(this));
                    });
                    // when the temporary context is gone requesting an injection returns null again:
                    Assert.Null(IoC_inject.Get <MyClass1>(this));

                    var myContextInstance2 = new MyClass1();
                    var testUser           = new MyUserClass1();
                    IoC_inject.DoWithTempContext <MyClass1>(myContextInstance2, () => {
                        IoC_inject.DoWithTempContext <MyUserClass1>(testUser, () => {
                            Assert.Equal(myContextInstance2, IoC_inject.Get <MyClass1>(this));
                            Assert.Equal(testUser, IoC_inject.Get <MyUserClass1>(this));
                        });
                    });
                    // when the temporary context is gone requesting an injection returns null again:
                    Assert.Null(IoC_inject.Get <MyClass1>(this));
                    Assert.Null(IoC_inject.Get <MyUserClass1>(this));
                });
            }
        }
Beispiel #5
0
        public async Task TestEventListeners()
        {
            using (ProgressV2 progress = new ProgressV2("p3", 200)) {
                var progressEventTriggered = false;
                progress.ProgressChanged += (o, newValue) => {
                    Log.e(JsonWriter.AsPrettyString(o));
                    Assert.Equal(100, newValue);
                    progressEventTriggered = true;
                };
                await TaskV2.Run(() => {
                    ((IProgress <double>)progress).Report(100);
                    Assert.False(progressEventTriggered);
                    Assert.Equal(100, progress.GetCount());
                    Assert.Equal(50, progress.percent);
                });

                Assert.Equal(100, progress.GetCount());
                Assert.Equal(50, progress.percent);

                // The progress callback is dispatched using the SynchronizationContext
                // of the constructor, so it will have some delay before being called:
                Assert.False(progressEventTriggered);
                await TaskV2.Delay(50); // Wait for progress update to be invoked

                Assert.True(progressEventTriggered);
            }
        }
Beispiel #6
0
        public IEnumerator TestThrowsAsyncPart1()
        {
            yield return(Assert.ThrowsAsync <FormatException>(async() => {
                await TaskV2.Delay(10);
                throw new FormatException();
            }).AsCoroutine());

            yield return(TaskV2.Run(TestThrowsAsyncPart2).AsCoroutine());
        }
Beispiel #7
0
 private static Task <ImageResult> ToImageResult(byte[] bytes)
 {
     return(TaskV2.Run(() => {
         var stream = new MemoryStream(bytes);
         var image = ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha);
         stream.Dispose();
         Conversion.stbi__vertical_flip(image.Data, image.Width, image.Height, 4);
         return Task.FromResult(image);
     }));
 }
Beispiel #8
0
        private static async Task CreateAndRunATaskThatFails()
        {
            Task myFailedTask = null;
            await Assert.ThrowsAsync <AggregateException>(async() => {
                myFailedTask = TaskV2.Run(() => { throw new Exception("Some error"); });
                await myFailedTask;
                Assert.True(myFailedTask.IsFaulted);
                Assert.True(myFailedTask.IsCompleted);
            });

            Assert.NotNull(myFailedTask);
            Assert.NotNull(myFailedTask.Exception);
        }
Beispiel #9
0
        public async Task TestRunWithTaskScheduler1()   // Aligned with the coroutine test TestExecuteRepeated1
        {
            QueuedTaskScheduler scheduler = new QueuedTaskScheduler(TaskScheduler.Default, maxConcurrencyLevel: 1);
            var cancel = new CancellationTokenSource();

            // Create both tasks at the same time:
            Task          t1 = TaskV2.Run(SomeAsyncTask1, cancel, scheduler);
            Task <string> t2 = TaskV2.Run(SomeAsyncTask2, cancel, scheduler);

            Assert.Equal(1, scheduler.GetRemainingScheduledTaskCount()); // 1 task started and 1 waiting
            Assert.Equal("Some string result", await t2);
            Assert.Equal(0, scheduler.GetRemainingScheduledTaskCount());

            // Since the scheduler allows only one task at a time, if t2 is done, t1 also must be completed:
            Assert.True(t1.IsCompleted);
        }
Beispiel #10
0
        public async Task TestRunWithTaskScheduler2()   // Aligned with the coroutine test TestExecuteRepeated1
        {
            var maxConcurrencyLevel       = 2;
            QueuedTaskScheduler scheduler = new QueuedTaskScheduler(TaskScheduler.Default, maxConcurrencyLevel);
            var cancel = new CancellationTokenSource();

            // Create both tasks at the same time:
            Task          t1 = TaskV2.Run(SomeAsyncTask1, cancel, scheduler);
            Task <string> t2 = TaskV2.Run(SomeAsyncTask2, cancel, scheduler);
            var           t3 = TaskV2.Run(SomeAsyncTask1, cancel, scheduler); // Add a 3rd task (will not be started)

            Assert.True(scheduler.GetRemainingScheduledTaskCount() >= 1);

            Assert.Equal("Some string result", await t2);

            // Check that now also task t3 was started:
            Assert.Equal(0, scheduler.GetRemainingScheduledTaskCount());

            // Since the scheduler allows 2 tasks at a time, t1 will not be complete when t2 is done:
            Assert.False(t1.IsCompleted);
            await t1;
        }
Beispiel #11
0
 public static Task <ImageResult> LoadImageInBackground(FileEntry imgFile)
 {
     return(TaskV2.Run(() => LoadAndDispose(imgFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read))));
 }
Beispiel #12
0
 public static Task <ImageResult> LoadImageInBackground(byte[] bytes)
 {
     return(TaskV2.Run(() => LoadAndDispose(new MemoryStream(bytes))));
 }
Beispiel #13
0
 public static Task <ImageResult> LoadImageInBackground(FileEntry imgFile)
 {
     AssertV2.IsTrue(imgFile.Exists, "!imgFile.Exists: " + imgFile);
     return(TaskV2.Run(() => LoadAndDispose(imgFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read))));
 }
Beispiel #14
0
 private static Task ParallelExec <T>(IEnumerable <T> data, Action <T> actionPerElement)
 {
     return(Task.WhenAll(data.Map(elem => TaskV2.Run(() => actionPerElement(elem)))));
 }
Beispiel #15
0
        public async Task RunTestTask()
        {
            MyUser1 initialState = null; // Initially no user is logged in
            var     store        = new DataStore <MyUser1>(MyReducers1.ReduceUser, initialState, Middlewares.NewLoggingMiddleware <MyUser1>());

            var links = gameObject.GetLinkMap();

            var loginButton           = links.Get <Button>("LoginBtn");
            var loginButtonWasClicked = loginButton.SetOnClickAction(async delegate {
                loginButton.gameObject.Destroy();
                await TaskV2.Run(async() => {
                    await TaskV2.Delay(1000);
                    store.Dispatch(new ActionLoginUser()
                    {
                        newLoggedInUser = new MyUser1("Karl")
                    });
                }).LogOnError();
                Assert.IsNotNull(store.GetState());
            });

            // Register a listener that is attached to the UI button to demonstrate that its no longer triggered once the button is destroyed:
            var userNameChangedCounter = 0;
            var subStateListener       = store.NewSubStateListenerForUnity(loginButton, user => user);

            subStateListener.AddStateChangeListener(x => x?.name, newName => {
                userNameChangedCounter++;
                Toast.Show("User name changed to " + newName);
                Assert.IsFalse(loginButton.IsDestroyed());
            }, triggerInstantToInit: false);

            var userInfoText1 = links.Get <InputField>("UserNameInput1");

            ConnectInputFieldUiToModel(userInfoText1, store);
            var userInfoText2 = links.Get <InputField>("UserNameInput2");

            ConnectInputFieldUiToModel(userInfoText2, store);

            var oldCounterValue = userNameChangedCounter;

            SimulateButtonClickOn("LoginBtn");
            await loginButtonWasClicked;

            Assert.IsTrue(loginButton.IsDestroyed());
            // Since the button was destroyed, the counter should not change anymore:
            Assert.AreEqual(oldCounterValue, userNameChangedCounter);

            Toast.Show("Changing user name from background thread...");
            await Task.Delay(2000);

            // When NewSubStateListener instead of NewSubStateListenerForUnity is used, the
            // event will arrive on the thread where it was dispatched:
            var wasCalledOnMainThread = true;

            store.NewSubStateListener(user => user).AddStateChangeListener(x => x.name, newName => {
                wasCalledOnMainThread = MainThread.isMainThread;
            }, triggerInstantToInit: false);

            await TaskV2.Run(async() => { store.Dispatch(new ChangeName()
                {
                    newName = "Caaarl"
                }); });

            Assert.AreEqual("Caaarl", store.GetState().name);
            Assert.IsFalse(wasCalledOnMainThread);
        }
        public async Task TestDispatchFromManyThreads()
        {
            var store  = new DataStore <MyModel>(ReduceMyModel, new MyModel(0), NewMiddleware());
            var oldVal = 0;

            store.AddStateChangeListener(x => x.val, (newVal) => {
                if (newVal != (oldVal + 1))
                {
                    throw new InvalidOperationException($"{oldVal} vs {newVal}");
                }
                oldVal = newVal;
            }, false);
            {
                var count = 100;
                var tasks = new List <Task>();
                for (int i = 0; i < count; i++)
                {
                    tasks.Add(TaskV2.Run(() => {
                        store.Dispatch(new MyAction()
                        {
                            val = 1
                        });
                    }));
                }
                await Task.WhenAll(tasks);

                Assert.Equal(count, store.GetState().val);
            }
            {
                var tasks  = new List <Task>();
                var tasks2 = new List <Task>();
                store.AddStateChangeListener(x => x.val, (newVal) => {
                    if (newVal <= 300)
                    {
                        store.Dispatch(new MyAction()
                        {
                            val = 1
                        });
                        tasks2.Add(TaskV2.Run(() => {
                            store.Dispatch(new MyAction()
                            {
                                val = 1
                            });
                        }));
                    }
                }, false);
                var count = 100;
                for (int i = 0; i < count; i++)
                {
                    store.Dispatch(new MyAction()
                    {
                        val = 1
                    });
                    tasks.Add(TaskV2.Run(() => {
                        store.Dispatch(new MyAction()
                        {
                            val = 1
                        });
                    }));
                }
                await Task.WhenAll(tasks);

                await Task.WhenAll(tasks2);

                Assert.Equal(count * 7, store.GetState().val);
            }
        }