/// <summary>
        /// invoke action, when fails call errorNotify to notify users if it is not null
        /// </summary>
        /// <param name="action"></param>
        /// <param name="errorNotify"></param>
        public void Invoke(Action action, Action <NotifyEventArgs> errorNotify = null)
        {
            if (action == null)
            {
                throw new ArgumentNullException("action is null");
            }

            int             tryCount  = 0;
            NotifyEventArgs eventArgs = null;

            while (true)
            {
                try
                {
                    action();
                    return;
                }
                catch (Exception ex)
                {
                    tryCount++;

                    #region error notify

                    if (eventArgs == null)
                    {
                        eventArgs = new NotifyEventArgs();
                    }
                    eventArgs.Enqueue(ex);

                    if (errorNotify != null && tryCount >= TryCount)
                    {
                        try { errorNotify(eventArgs); }
                        catch { }
                    }
                    #endregion

                    if (tryCount >= TryCount)
                    {
                        throw new RetryTimeOutException(eventArgs);
                    }

                    Thread.Sleep(TryInterval);
                }
            }
        }
        /// <summary>
        /// invoke func, when fails call errorNotify to notify users if it is not null
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="func"></param>
        /// <param name="obj"></param>
        /// <param name="errorNotify"></param>
        /// <returns></returns>
        public TResult Invoke <T, TResult>(Func <T, TResult> func, T obj, Action <NotifyEventArgs> errorNotify = null)
        {
            if (func == null)
            {
                throw new ArgumentNullException("action is null");
            }

            int             tryCount  = 0;
            NotifyEventArgs eventArgs = null;

            while (true)
            {
                try
                {
                    return(func(obj));
                }
                catch (Exception ex)
                {
                    tryCount++;

                    #region error notify

                    if (eventArgs == null)
                    {
                        eventArgs = new NotifyEventArgs();
                    }
                    eventArgs.Enqueue(ex);

                    if (errorNotify != null && tryCount >= TryCount)
                    {
                        try { errorNotify(eventArgs); }
                        catch { }
                    }
                    #endregion

                    if (tryCount >= TryCount)
                    {
                        throw new RetryTimeOutException(eventArgs);
                    }

                    Thread.Sleep(TryInterval);
                }
            }
        }
 public RetryTimeOutException(NotifyEventArgs args)
 {
     NotifyEventArgs = args;
 }