Ejemplo n.º 1
0
        public void Wait()
        {
            if (scheduler == null)
            {
                schedWait.Wait();
            }

            if (!IsCompleted)
            {
                scheduler.ParticipateUntil(this);
            }
            if (exception != null)
            {
                throw exception;
            }
            if (IsCanceled)
            {
                throw new AggregateException(new TaskCanceledException(this));
            }
        }
Ejemplo n.º 2
0
        public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
        {
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException("millisecondsTimeout");
            }

            bool result = IsCompleted;

            if (!result)
            {
                if (scheduler == null)
                {
                    Watch watch = Watch.StartNew();

                    schedWait.Wait(millisecondsTimeout, cancellationToken);
                    millisecondsTimeout = ComputeTimeout(millisecondsTimeout, watch);
                }

                var wait_event = new ManualResetEventSlim(false);
                CancellationTokenRegistration?registration = null;

                try {
                    if (cancellationToken.CanBeCanceled)
                    {
                        registration = cancellationToken.Register(wait_event.Set);
                    }

                    // FIXME: The implementation is wrong and slow
                    // It adds a continuation to the task which is then
                    // returned to parent causing all sort of problems when
                    // timeout is reached before task is finished
                    result = !scheduler.ParticipateUntil(this, wait_event, millisecondsTimeout);
                } finally {
                    if (registration.HasValue)
                    {
                        registration.Value.Dispose();
                    }
                }
            }

            if (IsCanceled)
            {
                throw new AggregateException(new TaskCanceledException(this));
            }

            if (exception != null)
            {
                throw exception;
            }

            return(result);
        }
Ejemplo n.º 3
0
        public static int WaitAny(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
        {
            if (tasks == null)
            {
                throw new ArgumentNullException("tasks");
            }
            if (tasks.Length == 0)
            {
                throw new ArgumentException("tasks is empty", "tasks");
            }
            if (tasks.Length == 1)
            {
                tasks[0].Wait(millisecondsTimeout, cancellationToken);
                return(0);
            }

            int                  numFinished        = 0;
            int                  indexFirstFinished = -1;
            int                  index        = 0;
            TaskScheduler        sched        = null;
            Task                 task         = null;
            Watch                watch        = Watch.StartNew();
            ManualResetEventSlim predicateEvt = new ManualResetEventSlim(false);

            foreach (Task t in tasks)
            {
                int indexResult = index++;
                t.ContinueWith(delegate {
                    if (numFinished >= 1)
                    {
                        return;
                    }
                    int result = Interlocked.Increment(ref numFinished);

                    // Check if we are the first to have finished
                    if (result == 1)
                    {
                        indexFirstFinished = indexResult;
                    }

                    // Stop waiting
                    predicateEvt.Set();
                }, TaskContinuationOptions.ExecuteSynchronously);

                if (sched == null && t.scheduler != null)
                {
                    task  = t;
                    sched = t.scheduler;
                }
            }

            // If none of task have a scheduler we are forced to wait for at least one to start
            if (sched == null)
            {
                var handles = Array.ConvertAll(tasks, t => t.schedWait.WaitHandle);
                int shandle = -1;
                if ((shandle = WaitHandle.WaitAny(handles, millisecondsTimeout)) == WaitHandle.WaitTimeout)
                {
                    return(-1);
                }
                sched = tasks[shandle].scheduler;
                task  = tasks[shandle];
                millisecondsTimeout = ComputeTimeout(millisecondsTimeout, watch);
            }

            // One task already finished
            if (indexFirstFinished != -1)
            {
                return(indexFirstFinished);
            }

            if (cancellationToken != CancellationToken.None)
            {
                cancellationToken.Register(predicateEvt.Set);
                cancellationToken.ThrowIfCancellationRequested();
            }

            sched.ParticipateUntil(task, predicateEvt, millisecondsTimeout);

            // Index update is still not done
            if (indexFirstFinished == -1)
            {
                SpinWait wait = new SpinWait();
                while (indexFirstFinished == -1)
                {
                    wait.SpinOnce();
                }
            }

            return(indexFirstFinished);
        }