示例#1
0
        /// <summary>
        /// Initialize the instance.
        /// </summary>
        /// <param name="owner">The object that "owns" this operation (or <c>null</c>).</param>
        /// <param name="callback">The delegate to call when the operation completes.</param>
        /// <param name="state">The application defined state.</param>
        /// <remarks>
        /// The owner parameter is optionally used to identify the object that "owns"
        /// this operation.  This parameter may be null or any object type.  Additional
        /// information will be tracked by <see cref="AsyncTracker" /> if the object implements the
        /// <see cref="IAsyncResultOwner" /> interface.
        /// </remarks>
        public AsyncResult(object owner, AsyncCallback callback, object state)
        {
            this.owner          = owner;
            this.callback       = callback;
            this.asyncState     = state;
            this.internalState  = default(TInternalState);
            this.ttd            = DateTime.MaxValue;
            this.result         = default(TResult);
            this.wait           = null;
            this.isCompleted    = false;
            this.syncCompletion = false;
            this.exception      = null;
            this.notifyQueued   = false;
#if DEBUG && !MOBILE_DEVICE
            this.isWaiting     = false;
            this.isReleased    = false;
            this.traceID       = -1;
            this.traceName     = null;
            this.inCallback    = false;
            this.disposed      = false;
            this.createStack   = CallStack.AsyncTrace(1, true);
            this.startStack    = null;
            this.notifyStack   = null;
            this.completeStack = null;
            this.waitStack     = null;
#endif
        }
示例#2
0
        public void Started()
        {
#if DEBUG && !MOBILE_DEVICE
            Trace("Started()");
            this.startStack = CallStack.AsyncTrace(1, true);

            AsyncTracker.Add(this);
            AsyncTracker.Yield();
#endif
        }
示例#3
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
        }
示例#4
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
        }
示例#5
0
            public override bool WaitOne()
            {
                using (TimedLock.Lock(owner))
                {
                    if (owner.WaitStack == null)
                    {
                        owner.WaitStack = CallStack.AsyncTrace(0, true);
                    }

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

                    isWaiting = true;
                }

                return(wait.WaitOne());
            }
示例#6
0
            public override bool WaitOne(int millisecondTimeout, bool exitContext)
            {
                using (TimedLock.Lock(owner))
                {
                    if (owner.WaitStack == null)
                    {
                        owner.WaitStack = CallStack.AsyncTrace(0, true);
                    }

                    if (!isWaiting)
                    {
                        throw new InvalidOperationException("Another thread is already waiting.");
                    }

                    isWaiting = true;
                }

                return(wait.WaitOne(millisecondTimeout, exitContext));
            }
示例#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
        }
示例#8
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
        }