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); }
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); }
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); }
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)); }); } }
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); } }
public IEnumerator TestThrowsAsyncPart1() { yield return(Assert.ThrowsAsync <FormatException>(async() => { await TaskV2.Delay(10); throw new FormatException(); }).AsCoroutine()); yield return(TaskV2.Run(TestThrowsAsyncPart2).AsCoroutine()); }
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); })); }
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); }
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); }
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; }
public static Task <ImageResult> LoadImageInBackground(FileEntry imgFile) { return(TaskV2.Run(() => LoadAndDispose(imgFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read)))); }
public static Task <ImageResult> LoadImageInBackground(byte[] bytes) { return(TaskV2.Run(() => LoadAndDispose(new MemoryStream(bytes)))); }
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)))); }
private static Task ParallelExec <T>(IEnumerable <T> data, Action <T> actionPerElement) { return(Task.WhenAll(data.Map(elem => TaskV2.Run(() => actionPerElement(elem))))); }
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); } }