示例#1
0
        /// <summary>
        /// Release the work items' wait handles
        /// </summary>
        /// <param name="waitableResults">An array of work item results</param>
        private static void ReleaseWaitHandles(IWaitableResult[] waitableResults)
        {
            for (int i = 0; i < waitableResults.Length; ++i)
            {
                WorkItemResult wir = (WorkItemResult)waitableResults[i].GetWorkItemResult();

                wir.GetWorkItem().ReleaseWaitHandle();
            }
        }
示例#2
0
        /// <summary>
        /// Waits for any of the work items in the specified array to complete, cancel, or timeout
        /// </summary>
        /// <param name="waitableResults">Array of work item result objects</param>
        /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
        /// <param name="exitContext">
        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 
        /// </param>
        /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
        /// <returns>
        /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
        /// </returns>
        internal static int WaitAny(
            IWaitableResult[] waitableResults,
            int millisecondsTimeout,
            bool exitContext,
            WaitHandle cancelWaitHandle)
        {
            WaitHandle[] waitHandles;

            if (null != cancelWaitHandle)
            {
                waitHandles = new WaitHandle[waitableResults.Length + 1];
                GetWaitHandles(waitableResults, waitHandles);
                waitHandles[waitableResults.Length] = cancelWaitHandle;
            }
            else
            {
                waitHandles = new WaitHandle[waitableResults.Length];
                GetWaitHandles(waitableResults, waitHandles);
            }

            int result = STPEventWaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);

            // Treat cancel as timeout
            if (null != cancelWaitHandle)
            {
                if (result == waitableResults.Length)
                {
                    result = STPEventWaitHandle.WaitTimeout;
                }
            }

            ReleaseWaitHandles(waitableResults);

            return result;
        }
示例#3
0
        /// <summary>
        /// Fill an array of wait handles with the work items wait handles.
        /// </summary>
        /// <param name="waitableResults">An array of work item results</param>
        /// <param name="waitHandles">An array of wait handles to fill</param>
        private static void GetWaitHandles(
            IWaitableResult[] waitableResults,
            WaitHandle[] waitHandles)
        {
            for (int i = 0; i < waitableResults.Length; ++i)
            {
                WorkItemResult wir = waitableResults[i].GetWorkItemResult() as WorkItemResult;
                Debug.Assert(null != wir, "All waitableResults must be WorkItemResult objects");

                waitHandles[i] = wir.GetWorkItem().GetWaitHandle();
            }
        }
示例#4
0
        /// <summary>
        /// Wait for all work items to complete
        /// </summary>
        /// <param name="waitableResults">Array of work item result objects</param>
        /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
        /// <param name="exitContext">
        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 
        /// </param>
        /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
        /// <returns>
        /// true when every work item in waitableResults has completed; otherwise false.
        /// </returns>
        internal static bool WaitAll(
            IWaitableResult[] waitableResults,
            int millisecondsTimeout,
            bool exitContext,
            WaitHandle cancelWaitHandle)
        {
            if (0 == waitableResults.Length)
            {
                return true;
            }

            bool success;
            WaitHandle[] waitHandles = new WaitHandle[waitableResults.Length];
            GetWaitHandles(waitableResults, waitHandles);

            if ((null == cancelWaitHandle) && (waitHandles.Length <= 64))
            {
                success = STPEventWaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
            }
            else
            {
                success = true;
                int millisecondsLeft = millisecondsTimeout;
                Stopwatch stopwatch = Stopwatch.StartNew();

                WaitHandle[] whs;
                if (null != cancelWaitHandle)
                {
                    whs = new WaitHandle[] { null, cancelWaitHandle };
                }
                else
                {
                    whs = new WaitHandle[] { null };
                }

                bool waitInfinitely = (Timeout.Infinite == millisecondsTimeout);
                // Iterate over the wait handles and wait for each one to complete.
                // We cannot use WaitHandle.WaitAll directly, because the cancelWaitHandle
                // won't affect it.
                // Each iteration we update the time left for the timeout.
                for (int i = 0; i < waitableResults.Length; ++i)
                {
                    // WaitAny don't work with negative numbers
                    if (!waitInfinitely && (millisecondsLeft < 0))
                    {
                        success = false;
                        break;
                    }

                    whs[0] = waitHandles[i];
                    int result = STPEventWaitHandle.WaitAny(whs, millisecondsLeft, exitContext);
                    if ((result > 0) || (STPEventWaitHandle.WaitTimeout == result))
                    {
                        success = false;
                        break;
                    }

                    if (!waitInfinitely)
                    {
                        // Update the time left to wait
                        millisecondsLeft = millisecondsTimeout - (int)stopwatch.ElapsedMilliseconds;
                    }
                }
            }
            // Release the wait handles
            ReleaseWaitHandles(waitableResults);

            return success;
        }