Commits

Igor Fesenko committed 90a3b5e

[+] add implementation of FluentTask<TArg,TResult>

Comments (0)

Files changed (3)

ConsoleTester/Program.cs

         static void Main(string[] args)
         {
             var exampleRunner = new ExampleRunner();
-            exampleRunner.RunSynchronouslyTestWithRetValue();
+            exampleRunner.RunSynchronouslyTestWithRetValueAndInputArg(2.5);
         }
     }
 
                  .RunSynchronously();
          }
 
+         public double RunSynchronouslyTestWithRetValueAndInputArg(double arg)
+         {
+             return new FluentTask<double,double>()
+                 .DoWork(d =>
+                             {
+                                 Console.WriteLine("Do work");
+                                 Console.WriteLine("Input: {0}",d);
+                                 Thread.Sleep(TimeSpan.FromSeconds(2.5));
+                                 return Math.Exp(d);
+                             })
+                 .OnException(Console.WriteLine)
+                 .SetDefaultResultOnException(-1.0)
+                 .SetTimeout(TimeSpan.FromSeconds(3.0))
+                 .SetDefaultResultOnTimeout(-2.0)
+                 .OnTimeout(() => Console.WriteLine("Timeout"))
+                 .OnComplete(Console.WriteLine)
+                 .RunSynchronously(arg);
+         }
+
          public void RunAsyncTest()
          {
              new FluentTask()

FluentTasks/FluentTask.cs

                         Thread.Sleep(runAfter);
                     }
 
-                    if (operationTimeout.Ticks != 0)
-                    {
-                        result = InnerMethods.DispatcherSmartInvoke(() => WaitFor<TResult>.Run(operationTimeout, doWorkAction), activeDispatcher);
-                    }
-                    else
-                    {
-                        result = InnerMethods.DispatcherSmartInvoke(doWorkAction, activeDispatcher);
-                    }
+                    result = operationTimeout.Ticks != 0
+                                 ? InnerMethods.DispatcherSmartInvoke(
+                                     () => WaitFor<TResult>.Run(operationTimeout, doWorkAction), activeDispatcher)
+                                 : InnerMethods.DispatcherSmartInvoke(doWorkAction, activeDispatcher);
                 }
             }
             catch (TimeoutException)
 
         #endregion
     }
+
+    public class FluentTask<TArg, TResult>
+    {
+        private Func<TArg, TResult> doWorkAction;
+        private Action<TResult> onCompleteAction;
+        private Action<Exception> onExceptionAction;
+        private Action onTimeoutAction;
+        private Dispatcher activeDispatcher;
+        private TimeSpan operationTimeout = new TimeSpan(0);
+        private TimeSpan runAfter = new TimeSpan(0);
+
+        private TResult userDefaultValueOnException;
+        private bool isUserSetDefaultValueOnException;
+
+        private TResult userDefaultValueOnTimeout;
+        private bool isUserSetDefaultValueOnTimeout;
+
+        public FluentTask<TArg, TResult> DoWork(Func<TArg, TResult> action)
+        {
+            if (action == null)
+            {
+                throw new ArgumentNullException();
+            }
+            doWorkAction = action;
+            return this;
+        }
+
+        public FluentTask<TArg, TResult> OnComplete(Action<TResult> action)
+        {
+            if (action == null)
+            {
+                throw new ArgumentNullException();
+            }
+            onCompleteAction = action;
+            return this;
+        }
+
+        public FluentTask<TArg, TResult> OnException(Action<Exception> action)
+        {
+            if (action == null)
+            {
+                throw new ArgumentNullException();
+            }
+            onExceptionAction = action;
+            return this;
+        }
+
+        public FluentTask<TArg, TResult> UseDispatcher(Dispatcher dispatcher)
+        {
+            if (dispatcher == null)
+            {
+                throw new ArgumentNullException();
+            }
+            activeDispatcher = dispatcher;
+            return this;
+        }
+
+        public FluentTask<TArg, TResult> SetTimeout(TimeSpan timeout)
+        {
+            operationTimeout = timeout;
+            return this;
+        }
+
+        public FluentTask<TArg, TResult> OnTimeout(Action action)
+        {
+            if (action == null)
+            {
+                throw new ArgumentNullException();
+            }
+            onTimeoutAction = action;
+            return this;
+        }
+
+        public FluentTask<TArg, TResult> StartAfter(TimeSpan duration)
+        {
+            runAfter = duration;
+            return this;
+        }
+
+        public FluentTask<TArg, TResult> SetDefaultResultOnException(TResult defaultResult)
+        {
+            userDefaultValueOnException = defaultResult;
+            isUserSetDefaultValueOnException = true;
+            return this;
+        }
+
+        public FluentTask<TArg, TResult> SetDefaultResultOnTimeout(TResult defaultResult)
+        {
+            userDefaultValueOnTimeout = defaultResult;
+            isUserSetDefaultValueOnTimeout = true;
+            return this;
+        }
+
+        #region Running
+
+        public TResult RunSynchronously(TArg arg)
+        {
+            var result = default(TResult);
+            try
+            {
+                if (doWorkAction != null)
+                {
+                    if (runAfter.Ticks != 0)
+                    {
+                        Thread.Sleep(runAfter);
+                    }
+
+                    result = operationTimeout.Ticks != 0
+                                 ? InnerMethods.DispatcherSmartInvoke(
+                                     () => WaitFor<TResult>.Run(operationTimeout, () => doWorkAction(arg)),
+                                     activeDispatcher)
+                                 : InnerMethods.DispatcherSmartInvoke(doWorkAction, arg, activeDispatcher);
+                }
+            }
+            catch (TimeoutException)
+            {
+                if (isUserSetDefaultValueOnTimeout)
+                {
+                    result = userDefaultValueOnTimeout;
+                }
+                if (onTimeoutAction != null)
+                {
+                    InnerMethods.DispatcherSmartInvoke(onTimeoutAction, activeDispatcher);
+                }
+            }
+            catch (Exception exception)
+            {
+                if (isUserSetDefaultValueOnException)
+                {
+                    result = userDefaultValueOnException;
+                }
+                if (onExceptionAction != null)
+                {
+                    InnerMethods.DispatcherSmartInvoke(onExceptionAction, exception, activeDispatcher);
+                }
+            }
+            finally
+            {
+                if (onCompleteAction != null)
+                {
+                    InnerMethods.DispatcherSmartInvoke(onCompleteAction, result, activeDispatcher);
+                }
+            }
+
+            return result;
+        }
+
+        public void RunAsync(TArg arg)
+        {
+            var tempArg = arg;
+            Task<TResult>.Factory.StartNew(() => RunSynchronously(tempArg));
+        }
+
+
+        #endregion
+    }
 }

FluentTasks/InnerMethods.cs

             return func.Invoke();
         }
 
+        static public TResult DispatcherSmartInvoke<TArg,TResult>(Func<TArg,TResult> func, TArg arg, Dispatcher activeDispatcher)
+        {
+            if (activeDispatcher != null)
+            {
+                if (!activeDispatcher.CheckAccess())
+                {
+                    return (TResult)activeDispatcher.Invoke(func, arg);
+                }
+            }
+
+            return func.Invoke(arg);
+        }
+
         #endregion
     }
 }