using System; using System.Threading; using NUnit.Framework; using Amib.Threading; namespace WorkItemsGroupTests { /// /// Summary description for DoTestPostExecute. /// [TestFixture] [Category("WorkItemsGroup")] public class TestPostExecution { /// /// /// [Test] public void DefaultPostExecute_AlwaysCall() { Assert.IsTrue(DoTestDefaultPostExecute(CallToPostExecute.Always, true)); } [Test] public void DefaultPostExecute_NeverCall() { Assert.IsTrue(DoTestDefaultPostExecute(CallToPostExecute.Never, false)); } [Test] public void DefaultPostExecute_CallWhenCanceled() { Assert.IsTrue(DoTestDefaultPostExecute(CallToPostExecute.WhenWorkItemCanceled, false)); } [Test] public void DefaultPostExecute_CallWhenNotCanceled() { Assert.IsTrue(DoTestDefaultPostExecute(CallToPostExecute.WhenWorkItemNotCanceled, true)); } /// /// /// [Test] public void PostExecute_AlwaysCall() { Assert.IsTrue(DoTestPostExecute(CallToPostExecute.Always, true)); } [Test] public void PostExecute_NeverCall() { Assert.IsTrue(DoTestPostExecute(CallToPostExecute.Never, false)); } [Test] public void PostExecute_CallWhenCanceled() { Assert.IsTrue(DoTestPostExecute(CallToPostExecute.WhenWorkItemCanceled, false)); } [Test] public void PostExecute_CallWhenNotCanceled() { Assert.IsTrue(DoTestPostExecute(CallToPostExecute.WhenWorkItemNotCanceled, true)); } /// /// /// [Test] public void PostExecuteWithCancel_AlwaysCall() { Assert.IsTrue(DoTestPostExecuteWithCancel(CallToPostExecute.Always, true)); } [Test] public void PostExecuteWithCancel_NeverCall() { Assert.IsTrue(DoTestPostExecuteWithCancel(CallToPostExecute.Never, false)); } [Test] public void PostExecuteWithCancel_CallWhenCanceled() { Assert.IsTrue(DoTestPostExecuteWithCancel(CallToPostExecute.WhenWorkItemCanceled, true)); } [Test] public void PostExecuteWithCancel_CallWhenNotCanceled() { Assert.IsTrue(DoTestPostExecuteWithCancel(CallToPostExecute.WhenWorkItemNotCanceled, false)); } private class PostExecuteResult { public ManualResetEvent wh = new ManualResetEvent(false); } /// /// Example of how to use the post execute callback /// private bool DoTestDefaultPostExecute(CallToPostExecute callToPostExecute, bool answer) { SmartThreadPool smartThreadPool = new SmartThreadPool(); WIGStartInfo wigStartInfo = new WIGStartInfo(); wigStartInfo.CallToPostExecute = callToPostExecute; wigStartInfo.PostExecuteWorkItemCallback = new PostExecuteWorkItemCallback(this.DoSomePostExecuteWork); IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue, wigStartInfo); bool success = false; PostExecuteResult postExecuteResult = new PostExecuteResult(); IWorkItemResult wir = workItemsGroup.QueueWorkItem( new WorkItemCallback(this.DoSomeWork), postExecuteResult); if (!wir.IsCompleted) { int result = (int)wir.GetResult(); success = (1 == result); success = success && (postExecuteResult.wh.WaitOne(1000, true) == answer); } smartThreadPool.Shutdown(); return success; } /// /// Example of how to use the post execute callback /// private bool DoTestPostExecute(CallToPostExecute callToPostExecute, bool answer) { SmartThreadPool smartThreadPool = new SmartThreadPool(); IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue); bool success = false; PostExecuteResult postExecuteResult = new PostExecuteResult(); IWorkItemResult wir = workItemsGroup.QueueWorkItem( new WorkItemCallback(this.DoSomeWork), postExecuteResult, new PostExecuteWorkItemCallback(this.DoSomePostExecuteWork), callToPostExecute); if (!wir.IsCompleted) { int result = (int)wir.GetResult(); success = (1 == result); success = success && (postExecuteResult.wh.WaitOne(1000, true) == answer); } smartThreadPool.Shutdown(); return success; } /// /// Example of how to queue a work item and then cancel it while it is in the queue. /// private bool DoTestPostExecuteWithCancel(CallToPostExecute callToPostExecute, bool answer) { // Create a SmartThreadPool with only one thread. // It just to show how to use the work item canceling feature SmartThreadPool smartThreadPool = new SmartThreadPool(); IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(1); bool success = false; PostExecuteResult postExecuteResult = new PostExecuteResult(); // Queue a work item that will occupy the thread in the pool workItemsGroup.QueueWorkItem( new WorkItemCallback(this.DoSomeWork), null); // Queue another work item that will wait for the first to complete IWorkItemResult wir = workItemsGroup.QueueWorkItem( new WorkItemCallback(this.DoSomeWork), postExecuteResult, new PostExecuteWorkItemCallback(this.DoSomePostExecuteWork), callToPostExecute); // Wait a while for the thread pool to start executing the first work item Thread.Sleep(100); // Cancel the second work item while it still in the queue if (wir.Cancel()) { success = (postExecuteResult.wh.WaitOne(1000, true) == answer); } smartThreadPool.Shutdown(); return success; } private object DoSomeWork(object state) { Thread.Sleep(1000); return 1; } private void DoSomePostExecuteWork(IWorkItemResult wir) { PostExecuteResult postExecuteResult = wir.State as PostExecuteResult; postExecuteResult.wh.Set(); } private object SignalCancel(object state) { ManualResetEvent cancelWaitHandle = state as ManualResetEvent; Thread.Sleep(250); cancelWaitHandle.Set(); return null; } } }