Esempio n. 1
0
        /// <summary>
        /// Obtains all of the corresponding safe wait handles and adds a ref to each. Since the <see cref="SafeWaitHandle"/>
        /// property is publically modifiable, this makes sure that we add and release refs one the same set of safe wait
        /// handles to keep them alive during a multi-wait operation.
        /// </summary>
        private static SafeWaitHandle[] ObtainSafeWaitHandles(
            RuntimeThread currentThread,
            WaitHandle[] waitHandles,
            out SafeWaitHandle[] rentedSafeWaitHandles)
        {
            Debug.Assert(currentThread == RuntimeThread.CurrentThread);
            Debug.Assert(waitHandles != null);
            Debug.Assert(waitHandles.Length > 0);
            Debug.Assert(waitHandles.Length <= MaxWaitHandles);

            rentedSafeWaitHandles = currentThread.RentWaitedSafeWaitHandleArray(waitHandles.Length);
            SafeWaitHandle[] safeWaitHandles = rentedSafeWaitHandles ?? new SafeWaitHandle[waitHandles.Length];
            bool             success         = false;

            try
            {
                for (int i = 0; i < waitHandles.Length; ++i)
                {
                    WaitHandle waitHandle = waitHandles[i];
                    if (waitHandle == null)
                    {
                        throw new ArgumentNullException("waitHandles[" + i + ']', SR.ArgumentNull_ArrayElement);
                    }

                    SafeWaitHandle safeWaitHandle = waitHandle._waitHandle;
                    if (safeWaitHandle == null)
                    {
                        // Throw ObjectDisposedException for backward compatibility even though it is not be representative of the issue
                        throw new ObjectDisposedException(null, SR.ObjectDisposed_Generic);
                    }

                    safeWaitHandle.DangerousAddRef();
                    safeWaitHandles[i] = safeWaitHandle;
                }
                success = true;
            }
            finally
            {
                if (!success)
                {
                    for (int i = 0; i < waitHandles.Length; ++i)
                    {
                        SafeWaitHandle safeWaitHandle = safeWaitHandles[i];
                        if (safeWaitHandle == null)
                        {
                            break;
                        }
                        safeWaitHandle.DangerousRelease();
                        safeWaitHandles[i] = null;
                    }

                    if (rentedSafeWaitHandles != null)
                    {
                        currentThread.ReturnWaitedSafeWaitHandleArray(rentedSafeWaitHandles);
                    }
                }
            }

            return(safeWaitHandles);
        }
Esempio n. 2
0
        public static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout)
        {
            if (waitHandles == null)
            {
                throw new ArgumentNullException(nameof(waitHandles), SR.ArgumentNull_Waithandles);
            }
            if (waitHandles.Length == 0)
            {
                //
                // Some history: in CLR 1.0 and 1.1, we threw ArgumentException in this case, which was correct.
                // Somehow, in 2.0, this became ArgumentNullException.  This was not fixed until Silverlight 2,
                // which went back to ArgumentException.
                //
                // Now we're in a bit of a bind.  Backward-compatibility requires us to keep throwing ArgumentException
                // in CoreCLR, and ArgumentNullException in the desktop CLR.  This is ugly, but so is breaking
                // user code.
                //
                throw new ArgumentNullException(nameof(waitHandles), SR.Argument_EmptyWaithandleArray);
            }
            if (waitHandles.Length > MaxWaitHandles)
            {
                throw new NotSupportedException(SR.NotSupported_MaxWaitHandles);
            }
            if (-1 > millisecondsTimeout)
            {
                throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
            }
            Contract.EndContractBlock();

            RuntimeThread currentThread = RuntimeThread.CurrentThread;

            SafeWaitHandle[] rentedSafeWaitHandles;
            SafeWaitHandle[] safeWaitHandles = ObtainSafeWaitHandles(currentThread, waitHandles, waitHandles.Length, out rentedSafeWaitHandles);
            try
            {
                return(WaitAllCore(currentThread, safeWaitHandles, waitHandles, millisecondsTimeout));
            }
            finally
            {
                for (int i = 0; i < waitHandles.Length; ++i)
                {
                    safeWaitHandles[i].DangerousRelease();
                    safeWaitHandles[i] = null;
                }

                if (rentedSafeWaitHandles != null)
                {
                    currentThread.ReturnWaitedSafeWaitHandleArray(rentedSafeWaitHandles);
                }
            }
        }
Esempio n. 3
0
        internal static int WaitAny(WaitHandle[] waitHandles, int numWaitHandles, int millisecondsTimeout)
        {
            if (waitHandles == null)
            {
                throw new ArgumentNullException(nameof(waitHandles), SR.ArgumentNull_Waithandles);
            }
            if (waitHandles.Length == 0)
            {
                throw new ArgumentException(SR.Argument_EmptyWaithandleArray);
            }
            if (MaxWaitHandles < waitHandles.Length)
            {
                throw new NotSupportedException(SR.NotSupported_MaxWaitHandles);
            }
            if (-1 > millisecondsTimeout)
            {
                throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
            }
            Contract.EndContractBlock();

            RuntimeThread currentThread = RuntimeThread.CurrentThread;

            SafeWaitHandle[] rentedSafeWaitHandles;
            SafeWaitHandle[] safeWaitHandles = ObtainSafeWaitHandles(currentThread, waitHandles, numWaitHandles, out rentedSafeWaitHandles);
            try
            {
                return(WaitAnyCore(currentThread, safeWaitHandles, waitHandles, numWaitHandles, millisecondsTimeout));
            }
            finally
            {
                for (int i = 0; i < numWaitHandles; ++i)
                {
                    safeWaitHandles[i].DangerousRelease();
                    safeWaitHandles[i] = null;
                }

                if (rentedSafeWaitHandles != null)
                {
                    currentThread.ReturnWaitedSafeWaitHandleArray(rentedSafeWaitHandles);
                }
            }
        }