Commits

Igor Fesenko committed fa1e615

[*] refactoring
[+] add implementation of FluentTask<TResult>

Comments (0)

Files changed (5)

ConsoleTester/Program.cs

 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.InteropServices;
-using System.Text;
 using System.Threading;
 using FluentTasks;
 
     {
         static void Main(string[] args)
         {
-            var testRunner = new TestRunner();
-            testRunner.RunSynchronouslyTest();
-
-            testRunner.RunAsyncTest();
-            for (int i = 0; i < 100; i++)
-            {
-                Console.WriteLine(i);
-                Thread.Sleep(1000);
-            }
+            var exampleRunner = new ExampleRunner();
+            exampleRunner.RunSynchronouslyTestWithRetValue();
         }
     }
 
-    class TestRunner
+    class ExampleRunner
     {
          public void RunSynchronouslyTest()
          {
                  .RunSynchronously();
          }
 
+         public int RunSynchronouslyTestWithRetValue()
+         {
+             return new FluentTask<int>()
+                 .DoWork(
+                     () =>
+                         {
+                             Console.WriteLine("Do work");
+                             Thread.Sleep(TimeSpan.FromSeconds(2.5));
+                             return (int)Math.Exp(new Random().NextDouble());
+                         })
+                 .OnException(Console.WriteLine)
+                 .SetDefaultResultOnException(-1)
+                 .SetTimeout(TimeSpan.FromSeconds(3))
+                 .SetDefaultResultOnTimeout(-2)
+                 .OnTimeout(() => Console.WriteLine("Timeout"))
+                 .OnComplete(Console.WriteLine)
+                 .RunSynchronously();
+         }
+
          public void RunAsyncTest()
          {
              new FluentTask()

FluentTasks/FluentTask.cs

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

FluentTasks/FluentTasks.csproj

     <Reference Include="WindowsBase" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="InnerMethods.cs" />
     <Compile Include="WaitFor.cs" />
     <Compile Include="FluentTask.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />

FluentTasks/InnerMethods.cs

+using System;
+using System.Windows.Threading;
+
+namespace FluentTasks
+{
+    internal sealed class InnerMethods
+    {
+        #region Dispatcher
+        
+        static public void DispatcherSmartInvoke(Action action, Dispatcher activeDispatcher)
+        {
+            if (activeDispatcher != null)
+            {
+                if (!activeDispatcher.CheckAccess())
+                {
+                    activeDispatcher.Invoke(action);
+                    return;
+                }
+            }
+            
+            action();    
+        }
+
+        static public void DispatcherSmartInvoke<T>(Action<T> action, T arg, Dispatcher activeDispatcher)
+        {
+            if (activeDispatcher != null)
+            {
+                if (!activeDispatcher.CheckAccess())
+                {
+                    activeDispatcher.Invoke(action, arg);
+                    return;
+                }
+            }
+
+            action(arg);
+        }
+
+        static public TResult DispatcherSmartInvoke<TResult>(Func<TResult> func, Dispatcher activeDispatcher)
+        {
+            if (activeDispatcher != null)
+            {
+                if (!activeDispatcher.CheckAccess())
+                {
+                    return (TResult)activeDispatcher.Invoke(func);
+                }
+            }
+
+            return func.Invoke();
+        }
+
+        #endregion
+    }
+}
 -------------
 
 FluentTask allows you to run operations in separate thread yet receive success, failure and progress update on the WPF UI thread so that you can have a responsive UI and carry out expensive operations in background. It's convenient to use than BackgroundWorker component. No need to decare events and preserve stuffs in private variables to access it from different event callbacks. You can return data from parallel thread to the success/fail callback safely in a strongly typed manner.
+
+Examples
+-------------
+
+	new FluentTask<int>()
+					 .DoWork(
+						 () =>
+							 {
+								 Console.WriteLine("Do work");
+								 Thread.Sleep(TimeSpan.FromSeconds(2.5));
+								 return (int)Math.Exp(new Random().NextDouble());
+							 })
+					 .OnException(Console.WriteLine)
+					 .SetDefaultResultOnException(-1)
+					 .SetTimeout(TimeSpan.FromSeconds(3))
+					 .SetDefaultResultOnTimeout(-2)
+					 .OnTimeout(() => Console.WriteLine("Timeout"))
+					 .OnComplete(Console.WriteLine)
+					 .RunAsync();