コード例 #1
0
        public void Lazy_EnsureSingleThreadSafeExecution()
        {
            counter = 42;

            var l = new Lazy <int>(delegate() { return(counter++); }, true);

            object monitor = new object();
            var    threads = new Thread[10];

            for (int i = 0; i < 10; ++i)
            {
                threads[i] = new Thread(delegate()
                {
                    lock (monitor)
                    {
                        Monitor.Wait(monitor);
                    }
                    int val = l.Value;
                });
            }
            for (int i = 0; i < 10; ++i)
            {
                threads[i].Start();
            }
            lock (monitor)
                Monitor.PulseAll(monitor);

            Assert.AreEqual(42, l.Value);
        }
コード例 #2
0
        private static void CancellationTokenCallback(object obj)
        {
            ManualResetEventSlim mre = obj as ManualResetEventSlim;

            Debug.Assert(mre != null, "Expected a ManualResetEventSlim");
            Debug.Assert(mre.m_lock != null); //the lock should have been created before this callback is registered for use.
            lock (mre.m_lock)
            {
                Monitor2.PulseAll(mre.m_lock); // awaken all waiters
            }
        }
コード例 #3
0
        /// <summary>
        /// Private helper to actually perform the Set.
        /// </summary>
        /// <param name="duringCancellation">Indicates whether we are calling Set() during cancellation.</param>
        /// <exception cref="T:System.OperationCanceledException">The object has been canceled.</exception>
        private void Set(bool duringCancellation)
        {
            // We need to ensure that IsSet=true does not get reordered past the read of m_eventObj
            // This would be a legal movement according to the .NET memory model.
            // The code is safe as IsSet involves an Interlocked.CompareExchange which provides a full memory barrier.
            IsSet = true;

            // If there are waiting threads, we need to pulse them.
            if (Waiters > 0)
            {
                Debug.Assert(m_lock != null); //if waiters>0, then m_lock has already been created.
                lock (m_lock)
                {
                    Monitor2.PulseAll(m_lock);
                }
            }

            ManualResetEvent eventObj = m_eventObj;

            //Design-decision: do not set the event if we are in cancellation -> better to deadlock than to wake up waiters incorrectly
            //It would be preferable to wake up the event and have it throw OCE. This requires MRE to implement cancellation logic

            if (eventObj != null && !duringCancellation)
            {
                // We must surround this call to Set in a lock.  The reason is fairly subtle.
                // Sometimes a thread will issue a Wait and wake up after we have set m_state,
                // but before we have gotten around to setting m_eventObj (just below). That's
                // because Wait first checks m_state and will only access the event if absolutely
                // necessary.  However, the coding pattern { event.Wait(); event.Dispose() } is
                // quite common, and we must support it.  If the waiter woke up and disposed of
                // the event object before the setter has finished, however, we would try to set a
                // now-disposed Win32 event.  Crash!  To deal with this race condition, we use a lock to
                // protect access to the event object when setting and disposing of it.  We also
                // double-check that the event has not become null in the meantime when in the lock.

                lock (eventObj)
                {
                    if (m_eventObj != null)
                    {
                        // If somebody is waiting, we must set the event.
                        m_eventObj.Set();
                    }
                }
            }

#if DEBUG
            m_lastSetTime = DateTime.UtcNow.Ticks;
#endif
        }
コード例 #4
0
        public void Monitor_PulseAll_Invalid()
        {
            var obj = new object();

            AssertExtensions.Throws <ArgumentNullException>("obj", () => Monitor.PulseAll(null));
        }