/// <summary>
        /// Invokes the delegate with the given arguments
        /// If one target throws an exception the other targets
        /// won't be handled anymore.
        /// </summary>
        /// <param name="args">the argument array to pass to the target</param>
        public void Invoke(object[] args)
        {
            WeakMulticastDelegate current = this;

            while (current != null)
            {
                int start = Environment.TickCount;

                if (current._weakRef == null)
                {
                    current._method.Invoke(null, args);
                }
                else if (current._weakRef.IsAlive)
                {
                    current._method.Invoke(current._weakRef.Target, args);
                }

                if (Environment.TickCount - start > 500)
                {
                    if (Log.IsWarnEnabled)
                    {
                        Log.Warn("Invoke took " + (Environment.TickCount - start) + "ms! " + current);
                    }
                }

                current = current._prev;
            }
        }
        /// <summary>
        /// Removes a normal delegate from this weak multicast delegate
        /// </summary>
        /// <param name="realDelegate">the normal delegate</param>
        /// <returns>the new weak multicast delegate</returns>
        private WeakMulticastDelegate Remove(Delegate realDelegate)
        {
            if (Equals(realDelegate))
            {
                return(_prev);
            }

            WeakMulticastDelegate current = _prev;
            WeakMulticastDelegate last    = this;

            while (current != null)
            {
                if (current.Equals(realDelegate))
                {
                    last._prev    = current._prev;
                    current._prev = null;
                    break;
                }

                last    = current;
                current = current._prev;
            }

            return(this);
        }
        /// <summary>
        /// Removes a normal delegate from a weak multicast delegate
        /// </summary>
        /// <param name="weakDelegate">the weak multicast delegate</param>
        /// <param name="realDelegate">the normal delegate</param>
        /// <returns>the new weak multicast delegate</returns>
        public static WeakMulticastDelegate Remove(WeakMulticastDelegate weakDelegate, Delegate realDelegate)
        {
            if (realDelegate == null || weakDelegate == null)
            {
                return(null);
            }

            return(weakDelegate.Remove(realDelegate));
        }
        /// <summary>
        /// Combines this weak multicast delegate with a normal delegate
        /// </summary>
        /// <param name="realDelegate">the normal delegate</param>
        /// <returns>this delegate</returns>
        private WeakMulticastDelegate Combine(Delegate realDelegate)
        {
            var head = new WeakMulticastDelegate(realDelegate);

            head._prev = _prev;
            _prev      = head;

            return(this);
        }
        /// <summary>
        /// Combines a weak multicast delegate with a normal delegate
        /// and makes sure the normal delegate has not been added yet.
        /// </summary>
        /// <param name="weakDelegate">the weak multicast delegate</param>
        /// <param name="realDelegate">the normal delegate</param>
        /// <returns>the new combined weak multicast delegate</returns>
        public static WeakMulticastDelegate CombineUnique(WeakMulticastDelegate weakDelegate, Delegate realDelegate)
        {
            if (realDelegate == null)
            {
                return(null);
            }

            return((weakDelegate == null) ? new WeakMulticastDelegate(realDelegate) : weakDelegate.CombineUnique(realDelegate));
        }
        /// <summary>
        /// Dumps the delegates in this multicast delegate to a string
        /// </summary>
        /// <returns>The string containing the formated dump</returns>
        public string Dump()
        {
            var builder = new StringBuilder();

            WeakMulticastDelegate current = this;
            int count = 0;

            while (current != null)
            {
                count++;
                if (current._weakRef == null)
                {
                    builder.Append("\t");
                    builder.Append(count);
                    builder.Append(") ");
                    builder.Append(current._method.Name);
                    builder.Append(Environment.NewLine);
                }
                else
                {
                    if (current._weakRef.IsAlive)
                    {
                        builder.Append("\t");
                        builder.Append(count);
                        builder.Append(") ");
                        builder.Append(current._weakRef.Target);
                        builder.Append(".");
                        builder.Append(current._method.Name);
                        builder.Append(Environment.NewLine);
                    }
                    else
                    {
                        builder.Append("\t");
                        builder.Append(count);
                        builder.Append(") INVALID.");
                        builder.Append(current._method.Name);
                        builder.Append(Environment.NewLine);
                    }
                }

                current = current._prev;
            }

            return(builder.ToString());
        }
        /// <summary>
        /// Combines this weak multicast delegate with a normal delegate
        /// Makes sure the delegate target has not been added yet
        /// </summary>
        /// <param name="realDelegate">the real delegate</param>
        /// <returns>the new weak multicast delegate</returns>
        private WeakMulticastDelegate CombineUnique(Delegate realDelegate)
        {
            bool found = Equals(realDelegate);

            if (!found && _prev != null)
            {
                WeakMulticastDelegate curNode = _prev;

                while (!found && curNode != null)
                {
                    if (curNode.Equals(realDelegate))
                    {
                        found = true;
                    }

                    curNode = curNode._prev;
                }
            }

            return(found ? this : Combine(realDelegate));
        }
        /// <summary>
        /// Invokes the delegate with the given arguments
        /// If one target throws an exception the other targets
        /// won't be affected.
        /// </summary>
        /// <param name="args">the argument array to pass to the target</param>
        public void InvokeSafe(object[] args)
        {
            WeakMulticastDelegate current = this;

            while (current != null)
            {
                int start = Environment.TickCount;

                try
                {
                    var target = current._weakRef.Target;
                    if (current._weakRef == null)
                    {
                        current._method.Invoke(null, args);
                    }
                    else if (target != null && current._weakRef.IsAlive)
                    {
                        current._method.Invoke(target, args);
                    }
                }
                catch (Exception ex)
                {
                    if (Log.IsErrorEnabled)
                    {
                        Log.Error("InvokeSafe", ex);
                    }
                }

                if (Environment.TickCount - start > 500)
                {
                    if (Log.IsWarnEnabled)
                    {
                        Log.Warn("InvokeSafe took " + (Environment.TickCount - start) + "ms! " + current);
                    }
                }

                current = current._prev;
            }
        }
        /// <summary>
        /// Combines a weak multicast delegate with a normal delegate
        /// </summary>
        /// <param name="weakDelegate">the weak multicast delegate</param>
        /// <param name="realDelegate">the normal delegate</param>
        /// <returns>the new combinded weak multicast delegate</returns>
        public static WeakMulticastDelegate Combine(WeakMulticastDelegate weakDelegate, Delegate realDelegate)
        {
            if (realDelegate == null)
                return null;

            return (weakDelegate == null) ? new WeakMulticastDelegate(realDelegate) : weakDelegate.Combine(realDelegate);
        }
        /// <summary>
        /// Removes a normal delegate from a weak multicast delegate
        /// </summary>
        /// <param name="weakDelegate">the weak multicast delegate</param>
        /// <param name="realDelegate">the normal delegate</param>
        /// <returns>the new weak multicast delegate</returns>
        public static WeakMulticastDelegate Remove(WeakMulticastDelegate weakDelegate, Delegate realDelegate)
        {
            if (realDelegate == null || weakDelegate == null)
                return null;

            return weakDelegate.Remove(realDelegate);
        }
        /// <summary>
        /// Combines this weak multicast delegate with a normal delegate
        /// </summary>
        /// <param name="realDelegate">the normal delegate</param>
        /// <returns>this delegate</returns>
        private WeakMulticastDelegate Combine(Delegate realDelegate)
        {
            var head = new WeakMulticastDelegate(realDelegate);
            head._prev = _prev;
            _prev = head;

            return this;
        }