private static bool BeforeInvoke(AsyncRes res)
        {
            //if marked as completed then we abort.
            if (res.IsCompleted)
            {
                return(false);
            }
            //if mode is 'allow' there is nothing to check.  Otherwise...
            if (res.RMode != ReenteranceMode.Allow)
            {
                //be threadsafe with our one and only member field
                lock (methodLocks)
                {
                    if (!methodLocks.ContainsKey(res.Method))
                    {
                        //make sure we have a generic locking object in the collection, it will already be there if we are reentering
                        methodLocks.Add(res.Method, new object());
                    }
                    //if bypass mode and we can't get or lock, we dump out.
                    if (res.RMode == ReenteranceMode.Bypass)
                    {
                        if (!Monitor.TryEnter(methodLocks[res.Method]))
                        {
                            res.result = AsyncAction.Reenterant;
                            return(false);
                        }
                    }
                    else
                    {
                        //Otherwise in 'stack' mode, we just wait until someone else releases it...
                        Monitor.Enter(methodLocks[res.Method]);
                    }

                    //if we are here, all is good.
                    //Set some properties on the result class to show when we started, and what thread we are on
                    res.isStarted = true;
                    res.startTime = DateTime.Now;
                    res.thread    = Thread.CurrentThread;
                }
            }

            return(true);
        }
        private static void FinishInvoke(AsyncRes res)
        {
            if (res == null)
            {
                return;
            }
            try
            {
                //finish a few more properties
                res.isCompleted  = true;
                res.completeTime = DateTime.Now;
                //set the resetevent, in case someone is using the waithandle to know when we have completed.
                res.mre.Set();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error setting wait handle on " + (res.Method ?? "NULL") + ex);
            }

            if (res.RMode != ReenteranceMode.Allow)
            {
                //if mode is bypass or stack, then we must have a lock that needs releasing
                try
                {
                    if (res.Method != null)
                    {
                        if (methodLocks.ContainsKey(res.Method))
                        {
                            Monitor.Exit(methodLocks[res.Method]);
                        }
                    }
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine("Error releasing reentrant lock on " + (res.Method ?? "NULL") + ex);
                }
            }
        }
        private static void FinishInvoke(AsyncRes res)
        {
            if (res == null) return;
            try
            {
                //finish a few more properties
                res.isCompleted = true;
                res.completeTime = DateTime.Now;
                //set the resetevent, in case someone is using the waithandle to know when we have completed.
                res.mre.Set();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error setting wait handle on " + (res.Method ?? "NULL") + ex);
            }

            if (res.RMode != ReenteranceMode.Allow)
            {
                //if mode is bypass or stack, then we must have a lock that needs releasing
                try
                {
                    if (res.Method != null)
                    {
                        if (methodLocks.ContainsKey(res.Method))
                        {
                            Monitor.Exit(methodLocks[res.Method]);
                        }
                    }
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine("Error releasing reentrant lock on " + (res.Method ?? "NULL") + ex);
                }
            }
        }
        private static bool BeforeInvoke(AsyncRes res)
        {
            //if marked as completed then we abort.
            if (res.IsCompleted) return false;
            //if mode is 'allow' there is nothing to check.  Otherwise...
            if (res.RMode != ReenteranceMode.Allow)
            {
                //be threadsafe with our one and only member field
                lock (methodLocks)
                {
                    if (!methodLocks.ContainsKey(res.Method))
                    {
                        //make sure we have a generic locking object in the collection, it will already be there if we are reentering
                        methodLocks.Add(res.Method, new object());
                    }
                    //if bypass mode and we can't get or lock, we dump out.
                    if (res.RMode == ReenteranceMode.Bypass)
                    {
                        if (!Monitor.TryEnter(methodLocks[res.Method]))
                        {
                            res.result = AsyncAction.Reenterant;
                            return false;
                        }
                    }
                    else
                    {
                        //Otherwise in 'stack' mode, we just wait until someone else releases it...
                        Monitor.Enter(methodLocks[res.Method]);
                    }

                    //if we are here, all is good.  
                    //Set some properties on the result class to show when we started, and what thread we are on
                    res.isStarted = true;
                    res.startTime = DateTime.Now;
                    res.thread = Thread.CurrentThread;
                }
            }

            return true;
        }
        /// <summary>
        /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed.
        /// </summary>
        /// <param name="d">A void delegate - can be cast to (Action) from an anonymous delgate.</param>
        /// <param name="dr">A delegate with a return value of some sort - can be cast to (Func&lt;object&gt;) from an anonymous delgate with a return.</param>
        /// <param name="state">A user object that can be tracked through the returned result</param>
        /// <param name="getRetVal">If true, and the method/delgete returns something, it is included in the AsyncRes returned (after the method completes)</param>
        /// <param name="tryThreadPool">True to use the TP, otherwise just go to a ful lthread - good for long running tasks.</param>
        /// <param name="rMode">If true, will make sure no other instances are running your method.</param>
        /// <returns>AsyncRes with all kind of goodies for waiting, result values, etc.</returns>
        private static AsyncRes Do(Func<object> dr, Action d, bool getRetVal, object state, bool tryThreadPool, ReenteranceMode rMode, bool isAsync, Dispatcher dispatcher)
        {
            //get a generic MethodInfo for checks..
            MethodInfo mi = ((dr != null) ? dr.Method : d.Method);
            //make a unique key for output usage
            string key = string.Format("{0}{1}{2}{3}", ((getRetVal) ? "<-" : ""), mi.DeclaringType, ((mi.IsStatic) ? ":" : "."), mi.Name);
            //our custom return value, holds our delegate, state, key, etc.
            AsyncRes res = new AsyncRes(state, ((dr != null) ? (Delegate)dr : (Delegate)d), key, rMode);

            //Create a delegate wrapper for what we will actually invoke..
            Action Action = (Action)delegate
            {
                if (!BeforeInvoke(res)) return; //checks for reentrance issues and sets us up
                try
                {
                    if (res.IsCompleted) return;
                    if (dr != null)
                    {
                        res.retVal = dr();//use this one if theres a return
                    }
                    else
                    {
                        d();//otherwise the simpler Action
                    }
                }
                catch (Exception ex)
                { //we never want a rogue exception on a random thread, it can't bubble up anywhere
                    System.Diagnostics.Debug.WriteLine("Async Exception:" + ex);
                }
                finally
                {
                    FinishInvoke(res);//this will fire our callback if they used it, and clean up
                }
            };

            if (dispatcher != null)
            {
                res.control = dispatcher;
                res.result = AsyncAction.ControlInvoked;
                if (!isAsync)
                {
                    if (dispatcher.CheckAccess())
                    {
                        res.completedSynchronously = true;
                        Action();
                    }
                    else
                    {
                        dispatcher.BeginInvoke(Action);
                    }
                }
                else
                {
                    dispatcher.BeginInvoke(Action);
                }
                return res;
            } //don't catch these errors - if this fails, we shouldn't try a real thread or threadpool!

            if (tryThreadPool)
            {
                //we are going to use the .NET threadpool
                try
                {
                    //this is what actually fires this task off..
                    bool result = ThreadPool.QueueUserWorkItem(delegate { Action(); });
                    if (result)
                    {
                        res.result = AsyncAction.ThreadPool;
                        //this means success in queueing and running the item
                        return res;
                    }
                    else
                    {
                        //according to docs, this "won't ever happen" - exception instead, but just for kicks.
                        System.Diagnostics.Debug.WriteLine("Failed to queue in threadpool. Method: " + key);
                    }

                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine("Failed to queue in threadpool: " + ex.Message, "Method: " + key);
                }
            }

            //if we got this far, then something up there failed, or they wanted a dedicated thread
            Thread t = new Thread((ThreadStart)delegate { Action(); }) { IsBackground = true, Name = ("Async_" + key) };
            res.result = AsyncAction.Thread;
            t.Start();

            return res;
        }
        /// <summary>
        /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed.
        /// </summary>
        /// <param name="d">A void delegate - can be cast to (Action) from an anonymous delgate.</param>
        /// <param name="dr">A delegate with a return value of some sort - can be cast to (Func&lt;object&gt;) from an anonymous delgate with a return.</param>
        /// <param name="state">A user object that can be tracked through the returned result</param>
        /// <param name="getRetVal">If true, and the method/delgete returns something, it is included in the AsyncRes returned (after the method completes)</param>
        /// <param name="tryThreadPool">True to use the TP, otherwise just go to a ful lthread - good for long running tasks.</param>
        /// <param name="rMode">If true, will make sure no other instances are running your method.</param>
        /// <returns>AsyncRes with all kind of goodies for waiting, result values, etc.</returns>
        private static AsyncRes Do(Func <object> dr, Action d, bool getRetVal, object state, bool tryThreadPool, ReenteranceMode rMode, bool isAsync, Dispatcher dispatcher)
        {
            //get a generic MethodInfo for checks..
            MethodInfo mi = ((dr != null) ? dr.Method : d.Method);
            //make a unique key for output usage
            string key = string.Format("{0}{1}{2}{3}", ((getRetVal) ? "<-" : ""), mi.DeclaringType, ((mi.IsStatic) ? ":" : "."), mi.Name);
            //our custom return value, holds our delegate, state, key, etc.
            AsyncRes res = new AsyncRes(state, ((dr != null) ? (Delegate)dr : (Delegate)d), key, rMode);

            //Create a delegate wrapper for what we will actually invoke..
            Action Action = (Action) delegate
            {
                if (!BeforeInvoke(res))
                {
                    return;                     //checks for reentrance issues and sets us up
                }
                try
                {
                    if (res.IsCompleted)
                    {
                        return;
                    }
                    if (dr != null)
                    {
                        res.retVal = dr();//use this one if theres a return
                    }
                    else
                    {
                        d();//otherwise the simpler Action
                    }
                }
                catch (Exception ex)
                { //we never want a rogue exception on a random thread, it can't bubble up anywhere
                    System.Diagnostics.Debug.WriteLine("Async Exception:" + ex);
                }
                finally
                {
                    FinishInvoke(res);//this will fire our callback if they used it, and clean up
                }
            };

            if (dispatcher != null)
            {
                res.control = dispatcher;
                res.result  = AsyncAction.ControlInvoked;
                if (!isAsync)
                {
                    if (dispatcher.CheckAccess())
                    {
                        res.completedSynchronously = true;
                        Action();
                    }
                    else
                    {
                        dispatcher.BeginInvoke(Action);
                    }
                }
                else
                {
                    dispatcher.BeginInvoke(Action);
                }
                return(res);
            } //don't catch these errors - if this fails, we shouldn't try a real thread or threadpool!

            if (tryThreadPool)
            {
                //we are going to use the .NET threadpool
                try
                {
                    //this is what actually fires this task off..
                    bool result = ThreadPool.QueueUserWorkItem(delegate { Action(); });
                    if (result)
                    {
                        res.result = AsyncAction.ThreadPool;
                        //this means success in queueing and running the item
                        return(res);
                    }
                    else
                    {
                        //according to docs, this "won't ever happen" - exception instead, but just for kicks.
                        System.Diagnostics.Debug.WriteLine("Failed to queue in threadpool. Method: " + key);
                    }
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine("Failed to queue in threadpool: " + ex.Message, "Method: " + key);
                }
            }

            //if we got this far, then something up there failed, or they wanted a dedicated thread
            Thread t = new Thread((ThreadStart) delegate { Action(); })
            {
                IsBackground = true, Name = ("Async_" + key)
            };

            res.result = AsyncAction.Thread;
            t.Start();

            return(res);
        }