Example #1
0
        /// <summary>
        /// Forwards queued completion notifications to the proper
        /// async result handler.
        /// </summary>
        /// <param name="state">The queued async result.</param>
        private static void OnComplete(object state)
        {
            AsyncResult <TResult, TInternalState> ar = (AsyncResult <TResult, TInternalState>)state;

#if DEBUG && !MOBILE_DEVICE
            ar.inCallback = true;
#endif
            try
            {
#if !MOBILE_DEVICE
                AsyncTracker.Yield();
#endif
                using (TimedLock.Lock(ar))
                {
#if DEBUG && !MOBILE_DEVICE
                    if (ar.disposed)
                    {
                        ar.Trace("OnComplete(): AsyncResult has been disposed before operation completes");
                        AsyncTracker.Dump(ar, "AsyncResult has been disposed before operation completes.");
                        SysLog.LogErrorStackDump("AsyncResult has been disposed before operation completes.");

                        if (Debugger.IsAttached)
                        {
                            Debugger.Break();
                        }
                    }

                    ar.Trace("Callback({0})", ar.callback == null ? "null" : "");
#endif
                    if (ar.callback == null)
                    {
                        return;
                    }

                    ar.isCompleted = true;
                    if (ar.wait != null)
                    {
                        ar.wait.Set();
                    }

                    ar.callback(ar);
                }
            }
            catch (Exception e)
            {
                SysLog.LogException(e);
            }
            finally
            {
#if DEBUG && !MOBILE_DEVICE
                ar.inCallback = false;
#endif

#if !MOBILE_DEVICE
                AsyncTracker.Yield();
#endif
            }
        }
Example #2
0
        public void Started()
        {
#if DEBUG && !MOBILE_DEVICE
            Trace("Started()");
            this.startStack = CallStack.AsyncTrace(1, true);

            AsyncTracker.Add(this);
            AsyncTracker.Yield();
#endif
        }
Example #3
0
        public static void Start(TimeSpan holdTime, TimeSpan maxTimeout, int yieldCount)
        {
#if DEBUG
            if (!Enable || Global != null)
            {
                return;
            }

            AsyncTracker.Global = new AsyncTracker(holdTime, maxTimeout, yieldCount);
#endif
        }
Example #4
0
        public static void Stop()
        {
#if DEBUG
            if (AsyncTracker.Global == null)
            {
                return;
            }

            AsyncTracker.Global.StopNow();
            AsyncTracker.Global  = null;
            AsyncTracker.Context = null;
#endif
        }
Example #5
0
        /// <summary>
        /// Blocks the current thread until the operation completes.
        /// This is more efficient than calling <b>AsyncWaitHandle.WaitOne()</b>
        /// since it won't allocate an event if the operation has already
        /// completed.
        /// </summary>
        public void Wait()
        {
#if DEBUG && !MOBILE_DEVICE
            using (TimedLock.Lock(this))
            {
                if (waitStack == null)
                {
                    waitStack = CallStack.AsyncTrace(0, true);
                }

                if (isWaiting)
                {
                    Trace("Wait(exception): Another thread is already waiting.");
                    throw new InvalidOperationException("Another thread is already waiting.");
                }

                if (isReleased)
                {
                    Trace("Wait(release): Already released");
                    return;
                }

                if (isCompleted)
                {
                    isReleased = true;
                    Trace("Wait(no wait): Result={0} Sync={1}", result == null ? "null" : result.ToString(), syncCompletion);
                    return;
                }

                isWaiting = true;
            }
#endif

#if !MOBILE_DEVICE
            AsyncTracker.Yield();
#endif

#if DEBUG && !MOBILE_DEVICE
            Trace("Wait(block)");
            ((AsyncEvent)this.AsyncWaitHandle).WaitOne();
            isReleased = true;
            Trace("Wait(release): Result={0} Sync={1}", result == null ? "null" : result.ToString(), syncCompletion);
#else
            this.AsyncWaitHandle.WaitOne();
#endif

#if !MOBILE_DEVICE
            AsyncTracker.Yield();
#endif
        }
Example #6
0
        /// <summary>
        /// Release any resources associated with this object.
        /// </summary>
        public void Dispose()
        {
            using (TimedLock.Lock(this))
            {
#if DEBUG && !MOBILE_DEVICE
                if (!isCompleted)
                {
                    AsyncTracker.Dump(this, "Disposing AsyncResult before operation completes.");
                    SysLog.LogErrorStackDump("Disposing AsyncResult before operation completes.");
                    return;
                }

                if (disposed)
                {
                    var sb = new StringBuilder(1024);

                    AsyncTracker.Dump(this, "AsyncResult has already been disposed.");

                    sb.AppendLine("AsyncResult has already been disposed.");
                    sb.AppendLine();
                    sb.AppendLine("Current stack:");
                    CallStack.AsyncTrace(1, true).Dump(sb);
                    sb.AppendLine();
                    sb.AppendLine("Completion stack:");
                    completeStack.Dump(sb);

                    SysLog.LogError(sb.ToString());
                    return;
                }

                this.disposed      = true;
                this.completeStack = CallStack.AsyncTrace(1, true);
#endif
                if (wait != null)
                {
                    wait.Close();
                    wait = null;
                }
            }

#if !MOBILE_DEVICE
            AsyncTracker.Yield();
#endif
        }
Example #7
0
        public void Started(bool traceEnable)
        {
#if DEBUG && !MOBILE_DEVICE
            if (traceEnable)
            {
                // The trace name will be the name of the object type and method
                // that called this method.

                var stack  = new CallStack(1, false);
                var method = stack.GetFrame(0).GetMethod();

                this.traceName = method.DeclaringType.Name + "." + method.Name;
                this.traceID   = AsyncTraceID.GetNextID();
            }

            Trace("Started()");
            this.startStack = CallStack.AsyncTrace(1, true);

            AsyncTracker.Add(this);
            AsyncTracker.Yield();
#endif
        }
Example #8
0
 /// <summary>
 /// Writes the async result's state in human readable form to the
 /// system log.
 /// </summary>
 public void Dump()
 {
     AsyncTracker.Dump(this, null);
 }
Example #9
0
 /// <summary>
 /// Writes the async result's state in human readable form to the
 /// system log.
 /// </summary>
 /// <param name="title">An optional title line (or <c>null</c>).</param>
 public void Dump(string title)
 {
     AsyncTracker.Dump(this, title);
 }
Example #10
0
        /// <summary>
        /// Notify the application that the operation is complete
        /// via the call back delegate.
        /// </summary>
        /// <param name="e">
        /// The exception to be thrown in the <see cref="Finish" /> method
        /// or <c>null</c> if the operation was completed successfully.
        /// </param>
        /// <remarks>
        /// <note>
        /// Although this method may be called more than once for
        /// a particular async result instance, all but the first call
        /// will be ignored.
        /// </note>
        /// </remarks>
        public void Notify(Exception e)
        {
#if DEBUG && !MOBILE_DEVICE
            // Wait up to a second to verify that Started() has been
            // called before reporting a warning.

            DateTime endTime = SysTime.Now + TimeSpan.FromSeconds(1);
            bool     started = this.startStack != null;

            while (!started && SysTime.Now < endTime)
            {
                Thread.Sleep(10);
                started = this.startStack != null;
            }

            if (!started)
            {
                Trace("Notify({0}): Warning: Started() not called", exception != null ? exception.GetType().Name : (result == null ? "null" : result.ToString()));
                AsyncTracker.Dump(this, "Warning: Started() not called before Notifiy()");
            }

            if (notifyQueued)
            {
                Trace("Notify({0}: Already queued)", exception != null ? exception.GetType().Name : (result == null ? "null" : result.ToString()));
                return;
            }

            Trace("Notify({0})", exception != null ? exception.GetType().Name : (result == null ? "null" : result.ToString()));
            notifyStack = CallStack.AsyncTrace(1, true);

            if (NotifyHook != null)
            {
                NotifyHook(this, e);
            }
#endif

#if !MOBILE_DEVICE
            AsyncTracker.Yield();
#endif
            using (TimedLock.Lock(this))
            {
                notifyQueued = true;
                if (isCompleted)
                {
                    return;     // We've already signaled completion
                }
                exception = e;

                if (callback != null)
                {
                    if (syncCompletion)
                    {
                        callback(this);
                    }
                    else
                    {
                        Helper.UnsafeQueueUserWorkItem(onComplete, this);
                    }
                }
                else
                {
                    isCompleted = true;
                    if (wait != null)
                    {
                        wait.Set();
                    }
                }
            }

#if !MOBILE_DEVICE
            AsyncTracker.Yield();
#endif
        }