예제 #1
0
파일: TaskEnv.cs 프로젝트: yonglehou/DReAM
        /// <summary>
        /// Invoke a zero arg action.
        /// </summary>
        /// <param name="handler">Action to invoke.</param>
        public void Invoke(Action handler)
        {
            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }
            if (_referenceCount < 1)
            {
                throw new InvalidOperationException("Cannot call invoke an unaquired TaskEnv");
            }
#pragma warning disable 219
            System.Diagnostics.StackTrace stacktrace = DebugUtil.GetStackTrace();
#pragma warning restore 219

            // check if handler can be invoked in-place or needs to queued up
            if (_dispatchQueue != null)
            {
                _dispatchQueue.QueueWorkItem(() => {
                    // store current thread-specific settings
                    TaskEnv previousEnv = _currentEnv;
                    try {
                        // set thread-specific settings
                        _currentEnv = this;

                        // execute handler
                        handler();
                    } catch (Exception e) {
                        _log.ErrorExceptionMethodCall(e, "Invoke: unhandled exception in handler");
                    } finally {
                        Release();

                        // restore thread-specific settings
                        _currentEnv = previousEnv;
                    }
                });
            }
            else
            {
                // store current thread-specific settings
                TaskEnv previousEnv = _currentEnv;
                try {
                    // set thread-specific settings
                    _currentEnv = this;

                    // execute handler
                    handler();
                } catch (Exception e) {
                    _log.WarnExceptionMethodCall(e, "Invoke: unhandled exception in handler");
                } finally {
                    Release();

                    // restore thread-specific settings
                    _currentEnv = previousEnv;
                }
            }
        }
예제 #2
0
 /// <summary>
 /// Enqueue a callback as a work item to be invoked with a provided <see cref="TaskEnv"/>.
 /// </summary>
 /// <typeparam name="T">Result value type of callback.</typeparam>
 /// <param name="dispatchQueue">DispatchQueue to enqueue work into.</param>
 /// <param name="callback">Work item callback.</param>
 /// <param name="env">Environment for work item invocation.</param>
 /// <param name="result">Synchronization handle for work item.</param>
 /// <returns>The synchronization handle provided to the method.</returns>
 public static Result <T> QueueWorkItemWithEnv <T>(this IDispatchQueue dispatchQueue, Func <T> callback, TaskEnv env, Result <T> result)
 {
     if (env == null)
     {
         throw new ArgumentException("env");
     }
     dispatchQueue.QueueWorkItem(env.MakeAction(callback, result));
     return(result);
 }
예제 #3
0
        /// <summary>
        /// Enqueue a callback as a work item to be invoked with the current <see cref="TaskEnv"/>.
        /// </summary>
        /// <typeparam name="T">Result value type of callback.</typeparam>
        /// <param name="dispatchQueue">DispatchQueue to enqueue work into.</param>
        /// <param name="callback">Work item callback.</param>
        /// <param name="result">Synchronization handle for work item.</param>
        /// <returns>The synchronization handle provided to the method.</returns>
        public static Result <T> QueueWorkItemWithCurrentEnv <T>(this IDispatchQueue dispatchQueue, Func <T> callback, Result <T> result)
        {
            var current = TaskEnv.CurrentOrNull;

            if (current != null)
            {
                return(dispatchQueue.QueueWorkItemWithEnv(callback, current, result));
            }
            if (result != null)
            {
                dispatchQueue.QueueWorkItem(delegate() {
                    try {
                        result.Return(callback());
                    } catch (Exception e) {
                        result.Throw(e);
                    }
                });
                return(result);
            }
            dispatchQueue.QueueWorkItem(() => callback());
            return(null);
        }
        /// <summary>
        /// Signal the RendezVousEvent.  If a receiver continuation is present, trigger it.
        /// Otherwise, store the signal until a continuation is registered.
        /// </summary>
        /// <exception cref="InvalidOperationException">The RendezVousEvent instance has already been signaled.</exception>
        public void Signal()
        {
            if (HasCompleted)
            {
                throw new InvalidOperationException("event has already been used");
            }
            object value = Interlocked.Exchange(ref _placeholder, TOKEN);

            if (value != null)
            {
                if (!(value is Action))
                {
                    throw new InvalidOperationException("event has already been signaled");
                }
                Action handler = (Action)value;
                Interlocked.Decrement(ref _pendingCounter);
                if (_captured)
                {
                    lock (Pending) {
                        Pending.Remove(this);
                    }
                }
                _placeholder = USED;
                if (_dispatchQueue != null)
                {
                    _dispatchQueue.QueueWorkItem(handler);
                }
                else
                {
                    try {
                        handler();
                    } catch (Exception e) {
                        // log exception, but ignore it; outer task is immune to it
                        _log.WarnExceptionMethodCall(e, "Signal: unhandled exception in continuation");
                    }
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Enqueue a callback as a work item to be invoked with the current <see cref="TaskEnv"/>.
        /// </summary>
        /// <param name="dispatchQueue">DispatchQueue to enqueue work into.</param>
        /// <param name="callback">Work item callback.</param>
        /// <param name="result">Synchronization handle for work item.</param>
        /// <returns>The synchronization handle provided to the method.</returns>
        public static Result QueueWorkItemWithCurrentEnv(this IDispatchQueue dispatchQueue, Action callback, Result result)
        {
            var current = TaskEnv.CurrentOrNull;

            if (current != null)
            {
                return(dispatchQueue.QueueWorkItemWithEnv(callback, current, result));
            }
            if (result != null)
            {
                dispatchQueue.QueueWorkItem(() => {
                    try {
                        callback();
                        result.Return();
                    } catch (Exception e) {
                        result.Throw(e);
                    }
                });
                return(result);
            }
            dispatchQueue.QueueWorkItem(callback);
            return(null);
        }
예제 #6
0
        public void EvictWorkItems()
        {
            // clear CurrentThread to avoid having the evicted items being immediately added back again to the thread (i.e. infinite loop)
            CurrentThread = null;
            try {
                Action item;

                // remove up to 100 items from the current threads work queue
                for (int i = 0; (i < 100) && _inbox.TryPop(out item); ++i)
                {
                    _queue.QueueWorkItem(item);
                }
            } finally {
                // restore CurrentThread before we exit
                CurrentThread = this;
            }
        }
예제 #7
0
        private static Result <int> Fibonacci(IDispatchQueue stp, int n, TimeSpan delay, Result <int> result)
        {
            if (!ReferenceEquals(result.Env.DispatchQueue, stp))
            {
                _log.Error(string.Format("ERROR: wrong task env {0}, expected {1}.", result.Env.DispatchQueue, stp));
            }
            stp.QueueWorkItem(delegate {
                Interlocked.Increment(ref _counter);
                switch (n)
                {
                case 0:
                    if (delay > TimeSpan.Zero)
                    {
                        Thread.Sleep(delay);
                    }
                    result.Return(0);
                    break;

                case 1:
                    if (delay > TimeSpan.Zero)
                    {
                        Thread.Sleep(delay);
                    }
                    result.Return(1);
                    break;

                default:
                    Result <int> a = Fibonacci(stp, n - 1, delay, new Result <int>(TimeSpan.MaxValue, TaskEnv.New(stp)));
                    Result <int> b = Fibonacci(stp, n - 2, delay, new Result <int>(TimeSpan.MaxValue, TaskEnv.New(stp)));
                    new AResult[] { a, b }.Join(new Result(TimeSpan.MaxValue, TaskEnv.New(stp))).WhenDone(_ => {
                        if (!ReferenceEquals(AsyncUtil.CurrentDispatchQueue, stp))
                        {
                            _log.Error(string.Format("ERROR: wrong queue {0}, expected {1}.", AsyncUtil.CurrentDispatchQueue, stp));
                        }
                        result.Return(a.Value + b.Value);
                    });
                    break;
                }
            });
            return(result);
        }
예제 #8
0
 private static Result<int> Fibonacci(IDispatchQueue stp, int n, TimeSpan delay, Result<int> result)
 {
     if(!ReferenceEquals(result.Env.DispatchQueue, stp)) {
         _log.Error(string.Format("ERROR: wrong task env {0}, expected {1}.", result.Env.DispatchQueue, stp));
     }
     stp.QueueWorkItem(delegate {
         Interlocked.Increment(ref _counter);
         switch(n) {
         case 0:
             if(delay > TimeSpan.Zero) {
                 Thread.Sleep(delay);
             }
             result.Return(0);
             break;
         case 1:
             if(delay > TimeSpan.Zero) {
                 Thread.Sleep(delay);
             }
             result.Return(1);
             break;
         default:
             Result<int> a = Fibonacci(stp, n - 1, delay, new Result<int>(TimeSpan.MaxValue, TaskEnv.New(stp)));
             Result<int> b = Fibonacci(stp, n - 2, delay, new Result<int>(TimeSpan.MaxValue, TaskEnv.New(stp)));
             new AResult[] { a, b }.Join(new Result(TimeSpan.MaxValue, TaskEnv.New(stp))).WhenDone(_ => {
                 if(!ReferenceEquals(Async.CurrentDispatchQueue, stp)) {
                     _log.Error(string.Format("ERROR: wrong queue {0}, expected {1}.", Async.CurrentDispatchQueue, stp));
                 }
                 result.Return(a.Value + b.Value);
             });
             break;
         }
     });
     return result;
 }