private static SynchronizationContext GetWinRTContext()
        {
            // Optimization: WinRT dispatchers are supported for STA and ASTA apartment types only
            if (Thread.GetCurrentApartmentType() != Thread.ApartmentType.STA)
            {
                return(null);
            }

            object dispatcher = WinRTInterop.Callbacks.GetCurrentWinRTDispatcher();

            if (dispatcher == null)
            {
                return(null);
            }

            return(s_winRTContextCache.GetValue(dispatcher, _dispatcher => new WinRTSynchronizationContext(_dispatcher)));
        }
예제 #2
0
        private static unsafe int WaitForMultipleObjectsIgnoringSyncContext(IntPtr *pHandles, int numHandles, bool waitAll, int millisecondsTimeout)
        {
            Debug.Assert(millisecondsTimeout >= -1);

            //
            // In the CLR, we use CoWaitForMultipleHandles to pump messages while waiting in an STA.  In that case, we cannot use WAIT_ALL.
            // That's because the wait would only be satisfied if a message arrives while the handles are signalled.
            //
            if (waitAll)
            {
                if (numHandles == 1)
                {
                    waitAll = false;
                }
                else if (Thread.GetCurrentApartmentType() == Thread.ApartmentType.STA)
                {
                    throw new NotSupportedException(SR.NotSupported_WaitAllSTAThread);
                }
            }

            Thread currentThread = Thread.CurrentThread;

            currentThread.SetWaitSleepJoinState();

            int result;

            if (Thread.ReentrantWaitsEnabled)
            {
                Debug.Assert(!waitAll);
                result = RuntimeImports.RhCompatibleReentrantWaitAny(false, millisecondsTimeout, numHandles, pHandles);
            }
            else
            {
                result = (int)Interop.Kernel32.WaitForMultipleObjectsEx((uint)numHandles, (IntPtr)pHandles, waitAll, (uint)millisecondsTimeout, false);
            }

            currentThread.ClearWaitSleepJoinState();

            if (result == Interop.Kernel32.WAIT_FAILED)
            {
                int errorCode = Interop.mincore.GetLastError();
                if (waitAll && errorCode == Interop.Errors.ERROR_INVALID_PARAMETER)
                {
                    // Check for duplicate handles. This is a brute force O(n^2) search, which is intended since the typical
                    // array length is short enough that this would actually be faster than using a hash set. Also, the worst
                    // case is not so bad considering that the array length is limited by
                    // <see cref="WaitHandle.MaxWaitHandles"/>.
                    for (int i = 1; i < numHandles; ++i)
                    {
                        IntPtr handle = pHandles[i];
                        for (int j = 0; j < i; ++j)
                        {
                            if (pHandles[j] == handle)
                            {
                                throw new DuplicateWaitObjectException("waitHandles[" + i + ']');
                            }
                        }
                    }
                }

                ThrowWaitFailedException(errorCode);
            }

            return(result);
        }