public bool TryGetEntity(UUID id, out ISceneEntity entity) { // Standard thread-safe lookup m_syncRoot.EnterReadLock(); try { return(m_entityUUIDs.TryGetValue(id, out entity)); } finally { m_syncRoot.ExitReadLock(); } }
public Cache.Group this[string name, UUID UUID] { get { Cache.Group group; SyncRoot.EnterReadLock(); nameUUIDHandleCache.TryGetValue(name, UUID, out group); SyncRoot.ExitReadLock(); return(group); } }
public Cache.Region this[string name] { get { Cache.Region region; SyncRoot.EnterReadLock(); nameCache.TryGetValue(name, out region); SyncRoot.ExitReadLock(); return(region); } }
public IEnumerator <T> GetEnumerator() { locker.EnterReadLock(); var tempFront = ((_front - 1) % _capacity).ToMinInt(0); var tempRear = _rear; if (_count > 0) { do { yield return(valueList[tempFront]); tempFront = (tempFront + 1) % _capacity; } while (tempFront != tempRear); //while (tempFront != tempRear) //{ //} } locker.ExitReadLock(); }
public bool TryGetAsset(UUID dataID, string contentType, out byte[] data) { string filename = GetFilename(dataID, contentType); m_rwLock.EnterReadLock(); try { if (File.Exists(filename)) { data = File.ReadAllBytes(filename); return(true); } string temporaryFilename = GetTemporaryFilename(dataID, contentType); if (File.Exists(temporaryFilename)) { data = File.ReadAllBytes(temporaryFilename); return(true); } } catch (Exception ex) { m_log.Error("Failed to fetch local data " + dataID + " (" + contentType + "): " + ex.Message); } finally { m_rwLock.ExitReadLock(); } data = null; return(false); }
public TValue this[TKey key] { get { _lock.EnterReadLock(); try { if (!_dictionary.TryGetValue(key, out var value)) { throw new InvalidOperationException($"key {key} doesn't exist"); } return(value); } finally { _lock.ExitReadLock(); } } set { _lock.EnterWriteLock(); _dictionary[key] = value; _lock.ExitWriteLock(); } }
public V Find(K key, Table <K, V> table) { ByteBuffer value = null; bool foundInSnapshot = false; snapshotLock.EnterReadLock(); try { Record <K, V> r; foundInSnapshot = snapshot.TryGetValue(key, out r); if (foundInSnapshot) { value = r.FindSnapshot(); } } finally { snapshotLock.ExitReadLock(); } if (foundInSnapshot) { return(null != value?table.DecodeValue(value) : null); } value = DatabaseTable.Find(table.EncodeKey(key)); return(null != value?table.DecodeValue(value) : null); }
public static PocoData ForType(Type t) { //#if !PETAPOCO_NO_DYNAMIC // if (t == typeof(System.Dynamic.ExpandoObject)) // throw new InvalidOperationException("Can't use dynamic types with this method"); //#endif // Check cache RWLock.EnterReadLock(); PocoData pd; try { if (m_PocoDatas.TryGetValue(t, out pd)) { return(pd); } } finally { RWLock.ExitReadLock(); } // Cache it RWLock.EnterWriteLock(); try { // Check again if (m_PocoDatas.TryGetValue(t, out pd)) { return(pd); } // Create it pd = new PocoData(t); m_PocoDatas.Add(t, pd); } finally { RWLock.ExitWriteLock(); } return(pd); }
public bool Contains(ulong handle) { //if (disposed) // return false; bool gotLock = false; try { try { } finally { m_rwLock.EnterReadLock(); gotLock = true; } return(m_byHandler.ContainsKey(handle & HANDLEMASK)); } finally { if (gotLock) { m_rwLock.ExitReadLock(); } } }
public WriteLock(ReaderWriterLockSlim rwLock) : base(rwLock) { if (rwLock.IsReadLockHeld) { rwLock.ExitReadLock(); _downGradeLockOnExit = true; } Lock.EnterWriteLock(); }
public void EntersReadLock() { var slim = new ReaderWriterLockSlim(); var token = slim.Read(); Assert.IsTrue(slim.IsReadLockHeld); slim.ExitReadLock(); slim.Dispose(); }
public static void EnterExit() { using (ReaderWriterLockSlim rwls = new ReaderWriterLockSlim()) { Assert.False(rwls.IsReadLockHeld); rwls.EnterReadLock(); Assert.True(rwls.IsReadLockHeld); rwls.ExitReadLock(); Assert.False(rwls.IsReadLockHeld); Assert.False(rwls.IsUpgradeableReadLockHeld); rwls.EnterUpgradeableReadLock(); Assert.True(rwls.IsUpgradeableReadLockHeld); rwls.ExitUpgradeableReadLock(); Assert.False(rwls.IsUpgradeableReadLockHeld); Assert.False(rwls.IsWriteLockHeld); rwls.EnterWriteLock(); Assert.True(rwls.IsWriteLockHeld); rwls.ExitWriteLock(); Assert.False(rwls.IsWriteLockHeld); Assert.False(rwls.IsUpgradeableReadLockHeld); rwls.EnterUpgradeableReadLock(); Assert.False(rwls.IsWriteLockHeld); Assert.True(rwls.IsUpgradeableReadLockHeld); rwls.EnterWriteLock(); Assert.True(rwls.IsWriteLockHeld); rwls.ExitWriteLock(); Assert.False(rwls.IsWriteLockHeld); Assert.True(rwls.IsUpgradeableReadLockHeld); rwls.ExitUpgradeableReadLock(); Assert.False(rwls.IsUpgradeableReadLockHeld); Assert.True(rwls.TryEnterReadLock(0)); rwls.ExitReadLock(); Assert.True(rwls.TryEnterReadLock(Timeout.InfiniteTimeSpan)); rwls.ExitReadLock(); Assert.True(rwls.TryEnterUpgradeableReadLock(0)); rwls.ExitUpgradeableReadLock(); Assert.True(rwls.TryEnterUpgradeableReadLock(Timeout.InfiniteTimeSpan)); rwls.ExitUpgradeableReadLock(); Assert.True(rwls.TryEnterWriteLock(0)); rwls.ExitWriteLock(); Assert.True(rwls.TryEnterWriteLock(Timeout.InfiniteTimeSpan)); rwls.ExitWriteLock(); } }
/// <summary> /// Gets the elements. /// </summary> /// <returns></returns> public IQueryable <Element> GetElements() { locker.EnterReadLock(); try { IEnumerable <Element> elements = Enumerable.Empty <Element>(); if (Directory.Exists(path)) { string[] files = Directory.GetFiles(path); for (int i = 0; i < files.Length; i++) { string fileName = files[i]; if (fileName.EndsWith(".resx")) { XDocument doc = XDocument.Load(files[i]); string culture; string category; ResXResourceFileHelper.Parse(fileName, out culture, out category); IEnumerable <Element> newElements = doc.Root.Elements("data") .Select(x => new Element() { Category = category, Culture = culture, Name = x.Attribute("name").Value, Value = x.Element("value").Value }); elements = elements.Union(newElements); } } } return(elements.AsQueryable <Element>()); } finally { locker.ExitReadLock(); } }
public void n3_multithreading() { int run = 1; int count = 1; const int max = 64; var exceptions = new List<Exception>(); var locker = new ReaderWriterLockSlim(); locker.EnterWriteLock(); for (int i = 0; i < max; i++) { ThreadPool.QueueUserWorkItem((_) => { Interlocked.Increment(ref count); locker.EnterReadLock(); locker.ExitReadLock(); try { while (Thread.VolatileRead(ref run) != 0) { DestroyReaders( CreateReaders(16), 0, false); } } catch (Exception ex) { exceptions.Add(ex); } Interlocked.Increment(ref count); }); } while (Thread.VolatileRead(ref count) < max) Thread.Sleep(100); count = 1; locker.ExitWriteLock(); Thread.Sleep(60000); run = 0; while (Thread.VolatileRead(ref count) < max) Thread.Sleep(1000); if (exceptions.Count > 0) throw exceptions[0]; }
public bool TryGetValue(TKey1 key, out TValue value) { bool success; rwLock.EnterReadLock(); try { success = Dictionary1.TryGetValue(key, out value); } finally { rwLock.ExitReadLock(); } return(success); }
public void OneManyLockIsFasterThanReaderWriterLockSlim() { // OneManyLock. var sw = Stopwatch.StartNew(); using (var oml = new OneManyLock()) { oml.Enter(true); M(); oml.Leave(true); for (Int32 i = 0; i < c_iterations; i++) { oml.Enter(true); M(); oml.Leave(true); } } Int64 omlElapsedMilliseconds = sw.ElapsedMilliseconds; // ReaderWriterLockSlim. sw.Restart(); using (var rwls = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion)) { rwls.EnterReadLock(); M(); rwls.ExitReadLock(); for (Int32 i = 0; i < c_iterations; i++) { rwls.EnterReadLock(); M(); rwls.ExitReadLock(); } } Int64 rwlsElapsedMilliseconds = sw.ElapsedMilliseconds; Assert.True(omlElapsedMilliseconds < rwlsElapsedMilliseconds); }
public void TestMethod2() { ISomething something = new Something(); var tasks = new List<Task>(); var rwlock = new ReaderWriterLockSlim(); for (var i = 0; i < 100; i++) { // These threads should never see "nothing".... tasks.Add(Task.Run(() => { for (var x = 0; x < 1000000; x++) { rwlock.EnterReadLock(); try { Thread.Sleep(100); Assert.That(something.IsNothing, Is.False); } finally { rwlock.ExitReadLock(); } } })); } // ... even though this one keeps setting it to nothing tasks.Add(Task.Run(() => { for (var x = 0; x < 1000000; x++) { rwlock.EnterWriteLock(); try { something = new Nothing(); Thread.Sleep(100); something = new Something(); } finally { rwlock.ExitWriteLock(); } } })); Task.WhenAll(tasks).Wait(); }
public Cache.Agent this[string firstname, string lastname] { get { Cache.Agent agent; SyncRoot.EnterReadLock(); nameHandleCache.TryGetValue(firstname, lastname, out agent); SyncRoot.ExitReadLock(); return(agent); } }
public bool IsWalkable(Point3 pos, bool isOversized) { _threadLock.EnterReadLock(); bool val = false; if (_cells.TryGetValue(pos, out var cell)) { val = cell.IsWalkable; if (isOversized && cell.IsEdge) { val = false; } } _threadLock.ExitReadLock(); return(val); }
public void Dispose() { ReaderWriterLockSlim copy = Interlocked.Exchange(ref rwlock, null); if (copy == null) { return; } switch (type) { case LockType.Read: copy.ExitReadLock(); break; case LockType.UpgradeableRead: copy.ExitUpgradeableReadLock(); break; case LockType.Write: copy.ExitWriteLock(); break; } }
private void ExitWriteLock(ReaderWriterLockSlim detectorLock) { detectorLock.ExitWriteLock(); detectorLock.EnterReadLock(); detectorLock.ExitUpgradeableReadLock(); detectorLock.ExitReadLock(); }
public static void ReadersMayBeConcurrent() { using (Barrier barrier = new Barrier(2)) using (ReaderWriterLockSlim rwls = new ReaderWriterLockSlim()) { Assert.Equal(0, rwls.CurrentReadCount); Task.WaitAll( Task.Run(() => { rwls.EnterReadLock(); barrier.SignalAndWait(); // 1 Assert.True(rwls.IsReadLockHeld); barrier.SignalAndWait(); // 2 Assert.Equal(2, rwls.CurrentReadCount); barrier.SignalAndWait(); // 3 barrier.SignalAndWait(); // 4 rwls.ExitReadLock(); }), Task.Run(() => { barrier.SignalAndWait(); // 1 rwls.EnterReadLock(); barrier.SignalAndWait(); // 2 Assert.True(rwls.IsReadLockHeld); Assert.Equal(0, rwls.WaitingReadCount); barrier.SignalAndWait(); // 3 rwls.ExitReadLock(); barrier.SignalAndWait(); // 4 })); Assert.Equal(0, rwls.CurrentReadCount); } }
public void TryEnterWriteLock_WhileReading () { var v = new ReaderWriterLockSlim (); AutoResetEvent ev = new AutoResetEvent (false); AutoResetEvent ev2 = new AutoResetEvent (false); Thread t1 = new Thread (() => { v.EnterReadLock (); ev2.Set (); ev.WaitOne (); v.ExitReadLock (); }); t1.Start (); ev2.WaitOne (); Assert.IsFalse (v.TryEnterWriteLock (100)); Assert.IsFalse (v.TryEnterReadLock (100)); ev.Set (); Assert.IsTrue (v.TryEnterWriteLock (100)); }
/// <summary> /// Handles a quark crossing request. Checks to see if the request is possible, and returns true or false based on /// the validity of the crossing to the actor who requested. This is performed in 3 steps: /// Step 1: Tell root to be ready to receive crossing requests for the object /// Root will also do sanity checks (e.g. object was deleted before crossing), so checking actorStatus code /// is important. /// Step 2: Root provides URL for uploading updated properties and for downloading said object. /// Step 3: Tell actor about the URL where it may contact the root directly. /// TODO: This can be optimized if we are allowed to remember or calculate the URL. We could respond immediately with the URL /// and the actor would keep trying it until root accepts it. For now, we avoid concurrency. /// </summary> /// <param name="context"></param> /// <param name="actorRequest"></param> private void HandleCrossing(HttpListenerContext context, HttpListenerRequest actorRequest) { StreamReader actorReader = new StreamReader(actorRequest.InputStream); XmlSerializer deserializer = new XmlSerializer(typeof(CrossingRequest)); CrossingRequest cross = (CrossingRequest)deserializer.Deserialize(actorReader); QuarkPublisher curQp = null, prevQp = null; string url = ""; HttpStatusCode status; m_crossLock.EnterReadLock(); try { m_log.InfoFormat("{0}: Handling Crossing. Time: {1}", LogHeader, DateTime.Now.Ticks); if (m_quarkSubscriptions.TryGetValue(cross.curQuark, out curQp) && m_quarkSubscriptions.TryGetValue(cross.prevQuark, out prevQp)) { if (curQp.RootActorID != prevQp.RootActorID) { // TODO: Inter-root communication } else { // Actor's response variables HttpListenerResponse actorResponse = context.Response; Stream actorOutput = actorResponse.OutputStream; // Root's request variables RootInfo root = (RootInfo)m_actor[curQp.RootActorID]; HttpWebRequest rootRequest = (HttpWebRequest)WebRequest.Create("http://" + root.quarkAddress + "/cross/"); rootRequest.Credentials = CredentialCache.DefaultCredentials; rootRequest.Method = "POST"; rootRequest.ContentType = "text/json"; Stream rootOutput = rootRequest.GetRequestStream(); status = ValidateCrossing(cross); if (status != HttpStatusCode.Created) { actorResponse.StatusCode = (int)status; actorOutput.Close(); actorResponse.Close(); return; } // From here on, I might have to write, make sure we only do one of these at a time. // Can't go in UpgradeableLock with a ReadLock, so let go first. m_crossLock.ExitReadLock(); m_crossLock.EnterUpgradeableReadLock(); try { // First we double check nothing changed while we were waiting for the lock, and we are still valid to cross. status = ValidateCrossing(cross); if (status != HttpStatusCode.Created) { actorResponse.StatusCode = (int)status; actorOutput.Close(); actorResponse.Close(); return; } // Step 1: Tell root to be ready to receive crossing requests for the object // Root will also do sanity checks (e.g. object was deleted before crossing), so checking actorStatus code // is important. OSDMap DataMap = new OSDMap(); DataMap["uuid"] = OSD.FromUUID(cross.uuid); DataMap["pq"] = OSD.FromString(cross.prevQuark); DataMap["cq"] = OSD.FromString(cross.curQuark); DataMap["ts"] = OSD.FromLong(cross.timestamp); string encodedMap = OSDParser.SerializeJsonString(DataMap, true); byte[] rootData = System.Text.Encoding.ASCII.GetBytes(encodedMap); int rootDataLength = rootData.Length; rootOutput.Write(rootData, 0, rootDataLength); rootOutput.Close(); // Step 2: Root provides URL for uploading updated properties and for downloading said object. HttpWebResponse response = (HttpWebResponse)rootRequest.GetResponse(); if (HttpStatusCode.OK == response.StatusCode) { m_crossLock.EnterWriteLock(); try { m_crossings[cross.uuid] = new CurrentCrossings(); m_crossings[cross.uuid].cross = cross; m_crossings[cross.uuid].actors.UnionWith(m_quarkSubscriptions[cross.prevQuark].GetAllQuarkSubscribers()); m_crossings[cross.uuid].actors.UnionWith(m_quarkSubscriptions[cross.curQuark].GetAllQuarkSubscribers()); // Remove the starting actor from the list of actors to ACK. m_crossings[cross.uuid].actors.Remove(cross.actorID); m_crossings[cross.uuid].rootHandler = root; } finally { m_crossLock.ExitWriteLock(); } Stream respData = response.GetResponseStream(); StreamReader rootReader = new StreamReader(respData); url = rootReader.ReadToEnd(); m_log.WarnFormat("{0}: Got URL for object request from server: {1}", LogHeader, url); if (url.Length > 0) { // Step 3: Tell actor about the URL where it may contact the root directly. // TODO: This can be optimized if we are allowed to remember or calculate the URL. We could respond immediately with the URL // and the actor would keep trying it until root accepts it. For now, we avoid concurrency. actorResponse.StatusCode = (int)HttpStatusCode.Created; byte[] actorUrlData = System.Text.Encoding.ASCII.GetBytes(url); int actorUrlDataLength = actorUrlData.Length; actorOutput.Write(actorUrlData, 0, actorUrlDataLength); actorOutput.Close(); actorResponse.Close(); } else { m_log.ErrorFormat("{0}: Received empty URL from Root", LogHeader); } } else { m_log.ErrorFormat("{0}: Failed to request crossing from root. Error Code: {1}", LogHeader, response.StatusCode); } } finally { m_crossLock.ExitUpgradeableReadLock(); } } } } catch (Exception e) { m_log.ErrorFormat("{0}: Failed to request crossing from root and forward to actor. Exception: {1}\n{2}", LogHeader, e, e.StackTrace); } finally { if (m_crossLock.IsReadLockHeld) { m_crossLock.ExitReadLock(); } } }
public void RecursiveEnterExitReadTest() { var v = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); v.EnterReadLock(); v.EnterReadLock(); v.EnterReadLock(); Assert.IsTrue(v.IsReadLockHeld); Assert.AreEqual(3, v.RecursiveReadCount); v.ExitReadLock(); Assert.IsTrue(v.IsReadLockHeld); Assert.AreEqual(2, v.RecursiveReadCount); }
public void ExitReadLock () { var v = new ReaderWriterLockSlim (); v.ExitReadLock (); }
static void Main(string[] args) { rwls = new System.Threading.ReaderWriterLockSlim(); DELG Read1 = (state) => { string thread = (string)state; while (true) { rwls.EnterReadLock(); try { Console.WriteLine("Thread -> {0} -- Message -> {1}", thread, val.ToString()); } finally { rwls.ExitReadLock(); } System.Threading.Thread.Sleep(2000); } }; DELG Write1 = (state) => { string thread = (string)state; int[] tb = { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 }; for (int i = 0; i < 10; i++) { rwls.EnterWriteLock(); try { val = tb[i]; Console.WriteLine("Changement de val par Thread -> {0}", thread); } finally { rwls.ExitWriteLock(); } System.Threading.Thread.Sleep(3000); } }; DELG Write2 = (state) => { string thread = (string)state; int[] tb = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 }; for (int i = 0; i < 10; i++) { rwls.EnterWriteLock(); try { val = tb[i]; Console.WriteLine("Changement de val par Thread -> {0}", thread); } finally { rwls.ExitWriteLock(); } System.Threading.Thread.Sleep(3000); } }; System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(Read1.Invoke)); System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(Read1.Invoke)); System.Threading.Thread t3 = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(Write1.Invoke)); System.Threading.Thread t4 = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(Write1.Invoke)); t1.Start((object)("T1")); t2.Start((object)("T2")); t3.Start((object)("T3")); t4.Start((object)("T4")); Console.Read(); }
public static void DontReleaseWaitingReadersWhenThereAreWaitingWriters() { using(var rwls = new ReaderWriterLockSlim()) { rwls.EnterUpgradeableReadLock(); rwls.EnterWriteLock(); // Typical order of execution: 0 // Add a waiting writer var threads = new Thread[2]; using(var beforeEnterWriteLock = new ManualResetEvent(false)) { var thread = new Thread(() => { beforeEnterWriteLock.Set(); rwls.EnterWriteLock(); // Typical order of execution: 3 rwls.ExitWriteLock(); }); thread.IsBackground = true; thread.Start(); threads[0] = thread; beforeEnterWriteLock.WaitOne(); } // Add a waiting reader using(var beforeEnterReadLock = new ManualResetEvent(false)) { var thread = new Thread(() => { beforeEnterReadLock.Set(); rwls.EnterReadLock(); // Typical order of execution: 4 rwls.ExitReadLock(); }); thread.IsBackground = true; thread.Start(); threads[1] = thread; beforeEnterReadLock.WaitOne(); } // Wait for the background threads to block waiting for their locks Thread.Sleep(1000); // Typical order of execution: 1 rwls.ExitWriteLock(); // At this point there is still one reader and one waiting writer, so the reader-writer lock should not try to // release any of the threads waiting for a lock // Typical order of execution: 2 rwls.ExitUpgradeableReadLock(); // At this point, the waiting writer should be released, and the waiting reader should not foreach(var thread in threads) thread.Join(); // Typical order of execution: 5 } }
private void Foo4() { var concurentDictionary = new Dictionary<int, int>(); var rwLockSlim = new ReaderWriterLockSlim(); var w = new ManualResetEvent(false); int timedCalled = 0; var threads = new List<Thread>(); int j; Lazy<int> lazy = new Lazy<int>(() => { Interlocked.Increment(ref timedCalled); return 1; }); for (int i = 0; i < Environment.ProcessorCount; i++) { threads.Add(new Thread(() => { w.WaitOne(); bool exist = false; rwLockSlim.EnterReadLock(); try { exist = concurentDictionary.TryGetValue(1, out j); } finally { rwLockSlim.ExitReadLock(); } if (!exist) { rwLockSlim.EnterUpgradeableReadLock(); try { if (!concurentDictionary.TryGetValue(1, out j)) { rwLockSlim.EnterWriteLock(); try { Interlocked.Increment(ref timedCalled); concurentDictionary[1] = 1; } finally { rwLockSlim.ExitWriteLock(); } } } finally { rwLockSlim.ExitUpgradeableReadLock(); } } })); threads.Last().Start(); } w.Set();//release all threads to start at the same time Thread.Sleep(100); Console.WriteLine(timedCalled);// output is 1 }
public void Start() { //ReaderWriterLockSlim locker = new ReaderWriterLockSlim(); //ParameterizedThreadStart reader = o => //{ // var innerlocker = locker; // int number = Convert.ToInt32(o); // for (int i = 0; i < 10; i++) // { // //进入读状态 那么下面的 thread2将会暂停运行 // locker.EnterReadLock(); // Console.WriteLine("Reading " + i); // Thread.Sleep(5000); // //退出读状态 下面的thread2将会继续运行 // locker.ExitReadLock(); // } //}; //ParameterizedThreadStart writer = o => //{ // var innerlocker = locker; // for (int i = 11; i < 200; i++) // { // //进入写状态 上面的线程thread1将会暂停运行 // Thread.Sleep(50);//睡一下 给上面的线程 执行锁定 locker.EnterReadLock(); // locker.EnterWriteLock(); // Console.WriteLine("Writing " + i); // //退出写状态 上面的线程thread1将会继续运行 // Thread.Sleep(500); // locker.ExitWriteLock(); // } //}; //Thread thread1 = new Thread(reader); //thread1.Start(); //Thread thread2 = new Thread(writer); //thread2.Start(); ReaderWriterLockSlim locker = new ReaderWriterLockSlim(); new Thread(new ParameterizedThreadStart(delegate { for (int i = 0; i < 100; i++) { Thread.Sleep(1); locker.EnterWriteLock(); Thread.Sleep(50); list.Add("t1-" + i); locker.ExitWriteLock(); } })).Start(); new Thread(new ParameterizedThreadStart(delegate { for (int i = 0; i < 100; i++) { Thread.Sleep(1); locker.EnterReadLock(); //locker.EnterWriteLock(); Thread.Sleep(50); list.Add("t2-" + i); //locker.ExitWriteLock(); locker.ExitReadLock(); } })).Start(); Thread.Sleep(20000);//20秒后输出结果 foreach (var item in list) { Console.WriteLine(item); } //总结 只要使用了同一个锁 那么 只要锁进入了任何一个状态 例如 EnterWriteLock 那么EnterReadLock 或者另外一个EnterWriteLock 所在的线程将会暂停运行 反之一样 Console.ReadLine(); }
private static void FreeReaderLock(ReaderWriterLockSlim oLock) { oLock.ExitReadLock(); }
// TypeCast_Overloads #endregion #region IEnumerable Members /// <summary> /// Returns an enumerator to iterate through the collection /// </summary> public IEnumerator GetEnumerator() { // http://www.csharphelp.com/archives/archive181.html List <T> localList; // init enumerator LockList.EnterReadLock(); try { // create a copy of m_TList localList = new List <T>(m_TList); } finally { LockList.ExitReadLock(); } // get the enumerator foreach (T item in localList) { yield return(item); } }
static void Main(string[] args) { // create the reader-writer lock ReaderWriterLockSlim rwlock = new ReaderWriterLockSlim(); // create a cancellation token source CancellationTokenSource tokenSource = new CancellationTokenSource(); // create an array of tasks Task[] tasks = new Task[5]; for (int i = 0; i < 5; i++) { // create a new task tasks[i] = new Task(() => { while (true) { // acqure the read lock rwlock.EnterReadLock(); // we now have the lock Console.WriteLine("Read lock acquired - count: {0}", rwlock.CurrentReadCount); // wait - this simulates a read operation tokenSource.Token.WaitHandle.WaitOne(1000); // release the read lock rwlock.ExitReadLock(); Console.WriteLine("Read lock released - count {0}", rwlock.CurrentReadCount); // check for cancellation tokenSource.Token.ThrowIfCancellationRequested(); } }, tokenSource.Token); // start the new task tasks[i].Start(); } // prompt the user Console.WriteLine("Press enter to acquire write lock"); // wait for the user to press enter Console.ReadLine(); // acquire the write lock Console.WriteLine("Requesting write lock"); rwlock.EnterWriteLock(); Console.WriteLine("Write lock acquired"); Console.WriteLine("Press enter to release write lock"); // wait for the user to press enter Console.ReadLine(); // release the write lock rwlock.ExitWriteLock(); // wait for 2 seconds and then cancel the tasks tokenSource.Token.WaitHandle.WaitOne(2000); tokenSource.Cancel(); try { // wait for the tasks to complete Task.WaitAll(tasks); } catch (AggregateException) { // do nothing } // wait for input before exiting Console.WriteLine("Press enter to finish"); Console.ReadLine(); }
public static void WriterToReaderChain() { using (AutoResetEvent are = new AutoResetEvent(false)) using (ReaderWriterLockSlim rwls = new ReaderWriterLockSlim()) { rwls.EnterWriteLock(); Task t = Task.Factory.StartNew(() => { Assert.False(rwls.TryEnterReadLock(TimeSpan.FromMilliseconds(10))); Task.Run(() => are.Set()); // ideally this won't fire until we've called EnterReadLock, but it's a benign race in that the test will succeed either way rwls.EnterReadLock(); rwls.ExitReadLock(); }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); are.WaitOne(); rwls.ExitWriteLock(); t.GetAwaiter().GetResult(); } }
// 线程返回 internal void _ThreadRun(bool doWait = true) { if (m_KdTree != null) { if (m_KdTreeStatus == KdTreeStatus.WaitRebuild) { m_KdTree.Rebuild(); m_KdTreeStatus = KdTreeStatus.Rebuilded; m_ReadWriterLock.EnterWriteLock(); m_VisibleQueueStatus = VisibleQueueStatus.WaitQuery; m_ReadWriterLock.ExitWriteLock(); } else if (m_KdTreeStatus == KdTreeStatus.Rebuilded) { VisibleQueueStatus status = this.CurrentQueueStatus; if (status == VisibleQueueStatus.Refresh) { if (m_LastVisibleHash != null) { m_LastVisibleHash.Clear(); } status = VisibleQueueStatus.WaitQuery; } if (status == VisibleQueueStatus.WaitQuery) { if (m_KdQuery == null) { m_KdQuery = new KDTree.KDQuery(100); } if (m_KdQueryIdxList == null) { m_KdQueryIdxList = new List <int> (); } else { m_KdQueryIdxList.Clear(); } Vector3 center; KdCameraInfo camInfo; m_ReadWriterLock.EnterReadLock(); try { camInfo = m_KdCamInfo; } finally { m_ReadWriterLock.ExitReadLock(); } float radius = camInfo.far; m_KdQuery.Radius(m_KdTree, camInfo.position, radius, m_KdQueryIdxList); int visibleCount = 0; int kdTreeVisibleCount = m_KdQueryIdxList.Count; m_TempHash.Clear(); if (m_KdQueryIdxList.Count > 0) { // 计算出摄影机面板 #if _USE_WORLD_AXIS KdCameraPanels camPanels = camInfo.CalcPanels(); #else Matrix4x4 mat = camInfo.CalcViewProjMatrix(); Vector4 nearPlane = camInfo.nearPlane; #endif for (int i = 0; i < m_KdQueryIdxList.Count; ++i) { int idx = m_KdQueryIdxList [i]; if (idx < 0 || idx >= m_KdTreeObjList.Count || idx >= m_VecArr.Length) { continue; } //Vector3 pos = m_VecArr [idx]; KdTreeObj obj = m_KdTreeObjList [idx]; //pos = camMVP.MultiplyPoint (pos); #if _USE_WORLD_AXIS bool isVisible = camInfo.IsBoundingSphereIn(obj.boundSphere, camPanels); #else bool isVisible = KdCameraInfo.IsBoundingSphereIn(obj.boundSphere, mat, nearPlane); //KdCameraInfo.NewPlane(camInfo.lookAt, camInfo.position) #endif // 摄影机剪裁 // 投递结果 if (isVisible) { ++visibleCount; m_TempHash.Add(obj.InstanceId); } } } // 查看和上一帧变化的 VisibleNode chgRoot = null; VisibleNode chgEndNode = null; if (m_TempHash.Count <= 0) { // 从有变到没有 if (m_LastVisibleHash != null) { var iter = m_LastVisibleHash.GetEnumerator(); while (iter.MoveNext()) { var visibleNode = GetVisibleNode(iter.Current, false); AddVisibleQueue(ref chgRoot, ref chgEndNode, visibleNode); } iter.Dispose(); m_LastVisibleHash.Clear(); } } else { if (m_LastVisibleHash == null) { m_LastVisibleHash = new HashSet <int> (); var iter = m_TempHash.GetEnumerator(); while (iter.MoveNext()) { var n = GetVisibleNode(iter.Current, true); AddVisibleQueue(ref chgRoot, ref chgEndNode, n); } iter.Dispose(); var tmp = m_LastVisibleHash; m_LastVisibleHash = m_TempHash; m_TempHash = tmp; } else { // rootNode下都是当前可见的 var iter = m_TempHash.GetEnumerator(); while (iter.MoveNext()) { bool isContains = m_LastVisibleHash.Contains(iter.Current); if (isContains) { m_LastVisibleHash.Remove(iter.Current); continue; } var chgN = GetVisibleNode(iter.Current, true); AddVisibleQueue(ref chgRoot, ref chgEndNode, chgN); } iter.Dispose(); // 剩下的就是从可见变成不可见 iter = m_LastVisibleHash.GetEnumerator(); while (iter.MoveNext()) { var chgN = GetVisibleNode(iter.Current, false); AddVisibleQueue(ref chgRoot, ref chgEndNode, chgN); } iter.Dispose(); // 交换一下 HashSet <int> tmp = m_LastVisibleHash; m_LastVisibleHash = m_TempHash; m_TempHash = tmp; m_TempHash.Clear(); } } VisibleNode tmpNode; m_ReadWriterLock.EnterWriteLock(); try { tmpNode = m_ChgVisibleQueue; m_VisibleCount = visibleCount; m_KdTreeVisible = kdTreeVisibleCount; m_ChgVisibleQueue = chgRoot; m_VisibleQueueStatus = VisibleQueueStatus.WaitChange; } finally { m_ReadWriterLock.ExitWriteLock(); } if (tmpNode != null) { ClearVisibleQueue(ref tmpNode); } } else { doWait = false; } } if (doWait && _cThreadWait > 0) { System.Threading.Thread.Sleep(_cThreadWait); } } }
public static void ReleaseReadersWhenWaitingWriterTimesOut() { using (var rwls = new ReaderWriterLockSlim()) { // Enter the read lock rwls.EnterReadLock(); // Typical order of execution: 0 Thread writeWaiterThread; using (var beforeTryEnterWriteLock = new ManualResetEvent(false)) { writeWaiterThread = new Thread(() => { // Typical order of execution: 1 // Add a writer to the wait list for enough time to allow successive readers to enter the wait list while this // writer is waiting beforeTryEnterWriteLock.Set(); if (rwls.TryEnterWriteLock(1000)) { // The typical order of execution is not guaranteed, as sleep times are not guaranteed. For // instance, before this write lock is added to the wait list, the two new read locks may be // acquired. In that case, the test may complete before or while the write lock is taken. rwls.ExitWriteLock(); } // Typical order of execution: 4 }); writeWaiterThread.IsBackground = true; writeWaiterThread.Start(); beforeTryEnterWriteLock.WaitOne(); } Thread.Sleep(500); // wait for TryEnterWriteLock to enter the wait list // A writer should now be waiting, add readers to the wait list. Since a read lock is still acquired, the writer // should time out waiting, then these readers should enter and exit the lock. ThreadStart EnterAndExitReadLock = () => { // Typical order of execution: 2, 3 rwls.EnterReadLock(); // Typical order of execution: 5, 6 rwls.ExitReadLock(); }; var readerThreads = new Thread[] { new Thread(EnterAndExitReadLock), new Thread(EnterAndExitReadLock) }; foreach (var readerThread in readerThreads) { readerThread.IsBackground = true; readerThread.Start(); } foreach (var readerThread in readerThreads) { readerThread.Join(); } rwls.ExitReadLock(); // Typical order of execution: 7 writeWaiterThread.Join(); } }
public void ReaderWriterLockUsage() { // для секций с известной операцией доступа (чтение или запись) можно использовать // ReaderWriterLockSlim (ReaderWriterLock не рекомендуется) ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim(); rwLock.EnterReadLock(); // критическая секция с чтением данных rwLock.ExitReadLock(); rwLock.EnterWriteLock(); // критическая секция с изменением данных rwLock.ExitWriteLock(); // также существует класс ConcurrentExclusiveSchedulerPair, // который содержит 2 менеджера заданий // все задания в ExclusiveScheduler выполняются по одному, // если не выполняется ни одно задание в ConcurrentScheduler // все задания в ConcurrentScheduler выполняются одновременно, // если не выполняется ни одно задание в ExclusiveScheduler ConcurrentExclusiveSchedulerPair schedulerPair = new ConcurrentExclusiveSchedulerPair(); TaskFactory exclusiveFactory = new TaskFactory(schedulerPair.ExclusiveScheduler); exclusiveFactory.StartNew(() => Console.WriteLine(DateTime.Now.ToLongTimeString())); // класс, который блокирует поток, пока внутренний счётчик не достигнет нуля CountdownEvent countdownEvent = new CountdownEvent(5); countdownEvent.Wait(); // критическая секция countdownEvent.Signal(2); // блокировка не снята countdownEvent.Signal(3); // блокировка снята // класс Barrier предоставляет возможность совокупности потоков проходить // через определённые шаги исполнения одновременно }
protected override void ExitLock(ReaderWriterLockSlim readerWriterLockSlim) { readerWriterLockSlim.ExitReadLock(); }
private void Exit( bool reEnterWriteLock, ReaderWriterLockSlim @lock ) { if ( reEnterWriteLock ) { if ( this.UseDeadlockDetection ) { MethodInterceptionArgs args = new MethodInterceptionArgsImpl( @lock, Arguments.Empty ) { TypedBinding = WriterReadLockBinding.Instance }; DeadlockDetectionPolicy.ReaderWriterEnhancements.Instance.OnWriterLockEnter( args ); } else { @lock.EnterWriteLock(); } } else { if ( this.UseDeadlockDetection ) { MethodExecutionArgs args = new MethodExecutionArgs( @lock, Arguments.Empty ); DeadlockDetectionPolicy.ReaderWriterEnhancements.Instance.OnReaderLockExit( args ); } @lock.ExitReadLock(); } }
public void RecursiveWriteUpgradeReadTest() { var rwlock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); rwlock.EnterWriteLock(); Assert.IsTrue(rwlock.IsWriteLockHeld); rwlock.EnterUpgradeableReadLock(); Assert.IsTrue(rwlock.IsUpgradeableReadLockHeld); rwlock.EnterReadLock(); Assert.IsTrue(rwlock.IsReadLockHeld); rwlock.ExitUpgradeableReadLock(); Assert.IsFalse(rwlock.IsUpgradeableReadLockHeld); Assert.IsTrue(rwlock.IsReadLockHeld); Assert.IsTrue(rwlock.IsWriteLockHeld); rwlock.ExitReadLock(); Assert.IsTrue(rwlock.IsWriteLockHeld); }
static void Main(string[] args) { // create the reader-writer lock ReaderWriterLockSlim rwlock = new ReaderWriterLockSlim(); // create a cancellation token source CancellationTokenSource tokenSource = new CancellationTokenSource(); // create some shared data int sharedData = 0; // create an array of tasks Task[] readerTasks = new Task[5]; for (int i = 0; i < readerTasks.Length; i++) { // create a new task readerTasks[i] = new Task(() => { while (true) { // acqure the read lock rwlock.EnterReadLock(); // we now have the lock Console.WriteLine("Read lock acquired - count: {0}", rwlock.CurrentReadCount); // read the shared data Console.WriteLine("Shared data value {0}", sharedData); // wait - slow things down to make the example clear tokenSource.Token.WaitHandle.WaitOne(1000); // release the read lock rwlock.ExitReadLock(); Console.WriteLine("Read lock released - count {0}", rwlock.CurrentReadCount); // check for cancellation tokenSource.Token.ThrowIfCancellationRequested(); } }, tokenSource.Token); // start the new task readerTasks[i].Start(); } Task[] writerTasks = new Task[2]; for (int i = 0; i < writerTasks.Length; i++) { writerTasks[i] = new Task(() => { while (true) { // acquire the upgradeable lock rwlock.EnterUpgradeableReadLock(); // simulate a branch that will require a write if (true) { // acquire the write lock rwlock.EnterWriteLock(); // print out a message with the details of the lock Console.WriteLine("Write Lock acquired - waiting readers {0}, writers {1}, upgraders {2}", rwlock.WaitingReadCount, rwlock.WaitingWriteCount, rwlock.WaitingUpgradeCount); // modify the shared data sharedData++; // wait - slow down the example to make things clear tokenSource.Token.WaitHandle.WaitOne(1000); // release the write lock rwlock.ExitWriteLock(); } // release the upgradable lock rwlock.ExitUpgradeableReadLock(); // check for cancellation tokenSource.Token.ThrowIfCancellationRequested(); } }, tokenSource.Token); // start the new task writerTasks[i].Start(); } // prompt the user Console.WriteLine("Press enter to cancel tasks"); // wait for the user to press enter Console.ReadLine(); // cancel the tasks tokenSource.Cancel(); try { // wait for the tasks to complete Task.WaitAll(readerTasks); } catch (AggregateException agex) { agex.Handle(ex => true); } // wait for input before exiting Console.WriteLine("Press enter to finish"); Console.ReadLine(); }
public void EnterUpgradeableReadLock () { var v = new ReaderWriterLockSlim (); v.EnterUpgradeableReadLock (); Assert.IsTrue (v.IsUpgradeableReadLockHeld, "A"); Assert.AreEqual (0, v.RecursiveWriteCount, "A1"); Assert.AreEqual (0, v.RecursiveReadCount, "A2"); Assert.AreEqual (1, v.RecursiveUpgradeCount, "A3"); Assert.AreEqual (0, v.WaitingReadCount, "A4"); Assert.AreEqual (0, v.WaitingUpgradeCount, "A5"); Assert.AreEqual (0, v.WaitingWriteCount, "A6"); v.ExitUpgradeableReadLock (); v.EnterUpgradeableReadLock (); Assert.IsTrue (v.IsUpgradeableReadLockHeld, "B"); Assert.AreEqual (0, v.RecursiveWriteCount, "B1"); Assert.AreEqual (0, v.RecursiveReadCount, "B2"); Assert.AreEqual (1, v.RecursiveUpgradeCount, "B3"); Assert.AreEqual (0, v.WaitingReadCount, "B4"); Assert.AreEqual (0, v.WaitingUpgradeCount, "B5"); Assert.AreEqual (0, v.WaitingWriteCount, "B6"); v.EnterReadLock (); v.ExitUpgradeableReadLock (); Assert.IsTrue (v.IsReadLockHeld, "C"); Assert.AreEqual (0, v.RecursiveWriteCount, "C1"); Assert.AreEqual (1, v.RecursiveReadCount, "C2"); Assert.AreEqual (0, v.RecursiveUpgradeCount, "C3"); Assert.AreEqual (0, v.WaitingReadCount, "C4"); Assert.AreEqual (0, v.WaitingUpgradeCount, "C5"); Assert.AreEqual (0, v.WaitingWriteCount, "C6"); v.ExitReadLock (); }
public static void DeadlockAvoidance() { using (ReaderWriterLockSlim rwls = new ReaderWriterLockSlim()) { rwls.EnterReadLock(); Assert.Throws<LockRecursionException>(() => rwls.EnterReadLock()); Assert.Throws<LockRecursionException>(() => rwls.EnterUpgradeableReadLock()); Assert.Throws<LockRecursionException>(() => rwls.EnterWriteLock()); rwls.ExitReadLock(); rwls.EnterUpgradeableReadLock(); rwls.EnterReadLock(); Assert.Throws<LockRecursionException>(() => rwls.EnterReadLock()); rwls.ExitReadLock(); Assert.Throws<LockRecursionException>(() => rwls.EnterUpgradeableReadLock()); rwls.EnterWriteLock(); Assert.Throws<LockRecursionException>(() => rwls.EnterWriteLock()); rwls.ExitWriteLock(); rwls.ExitUpgradeableReadLock(); rwls.EnterWriteLock(); Assert.Throws<LockRecursionException>(() => rwls.EnterReadLock()); Assert.Throws<LockRecursionException>(() => rwls.EnterUpgradeableReadLock()); Assert.Throws<LockRecursionException>(() => rwls.EnterWriteLock()); rwls.ExitWriteLock(); } using (ReaderWriterLockSlim rwls = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion)) { rwls.EnterReadLock(); Assert.Throws<LockRecursionException>(() => rwls.EnterWriteLock()); rwls.EnterReadLock(); Assert.Throws<LockRecursionException>(() => rwls.EnterUpgradeableReadLock()); rwls.ExitReadLock(); rwls.ExitReadLock(); rwls.EnterUpgradeableReadLock(); rwls.EnterReadLock(); rwls.EnterUpgradeableReadLock(); rwls.ExitUpgradeableReadLock(); rwls.EnterReadLock(); rwls.ExitReadLock(); rwls.ExitReadLock(); rwls.EnterWriteLock(); rwls.EnterWriteLock(); rwls.ExitWriteLock(); rwls.ExitWriteLock(); rwls.ExitUpgradeableReadLock(); rwls.EnterWriteLock(); rwls.EnterReadLock(); rwls.ExitReadLock(); rwls.EnterUpgradeableReadLock(); rwls.ExitUpgradeableReadLock(); rwls.EnterWriteLock(); rwls.ExitWriteLock(); rwls.ExitWriteLock(); } }
public void RecursiveWritePlusReadLockTest () { var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion); Assert.IsTrue (v.TryEnterWriteLock (100), "#1"); Assert.AreEqual (1, v.RecursiveWriteCount, "1b"); Assert.AreEqual (0, v.RecursiveReadCount, "1c"); Assert.IsTrue (v.TryEnterReadLock (100), "#2"); Assert.AreEqual (1, v.RecursiveWriteCount, "2b"); Assert.AreEqual (1, v.RecursiveReadCount, "2c"); Assert.IsTrue (v.TryEnterReadLock (100), "#3"); Assert.AreEqual (1, v.RecursiveWriteCount, "3b"); Assert.AreEqual (2, v.RecursiveReadCount, "3c"); v.ExitReadLock (); Assert.AreEqual (1, v.RecursiveWriteCount, "4b"); Assert.AreEqual (1, v.RecursiveReadCount, "4c"); }
public static void InvalidExits(LockRecursionPolicy policy) { using (ReaderWriterLockSlim rwls = new ReaderWriterLockSlim(policy)) { Assert.Throws<SynchronizationLockException>(() => rwls.ExitReadLock()); Assert.Throws<SynchronizationLockException>(() => rwls.ExitUpgradeableReadLock()); Assert.Throws<SynchronizationLockException>(() => rwls.ExitWriteLock()); rwls.EnterReadLock(); Assert.Throws<SynchronizationLockException>(() => rwls.ExitUpgradeableReadLock()); Assert.Throws<SynchronizationLockException>(() => rwls.ExitWriteLock()); rwls.ExitReadLock(); rwls.EnterUpgradeableReadLock(); Assert.Throws<SynchronizationLockException>(() => rwls.ExitReadLock()); Assert.Throws<SynchronizationLockException>(() => rwls.ExitWriteLock()); rwls.ExitUpgradeableReadLock(); rwls.EnterWriteLock(); Assert.Throws<SynchronizationLockException>(() => rwls.ExitReadLock()); Assert.Throws<SynchronizationLockException>(() => rwls.ExitUpgradeableReadLock()); rwls.ExitWriteLock(); using (Barrier barrier = new Barrier(2)) { Task t = Task.Factory.StartNew(() => { rwls.EnterWriteLock(); barrier.SignalAndWait(); barrier.SignalAndWait(); rwls.ExitWriteLock(); }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); barrier.SignalAndWait(); Assert.Throws<SynchronizationLockException>(() => rwls.ExitWriteLock()); barrier.SignalAndWait(); t.GetAwaiter().GetResult(); } } }
public static void ReleaseReadOnlyLock(ReaderWriterLockSlim locks) { if (locks.IsReadLockHeld) locks.ExitReadLock(); }
/// <summary> /// Lock our inventory list for reading (many can read, one can write) /// </summary> public void LockItemsForRead(bool locked) { if (locked) { if (m_itemLock.IsWriteLockHeld && LockedByThread != null) { if (!LockedByThread.IsAlive) { //Locked by dead thread, reset. m_itemLock = new System.Threading.ReaderWriterLockSlim(); } } if (m_itemLock.RecursiveReadCount > 0) { m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); try { // That call stack is useful for end users only. RealProgrammers need a full dump. Commented. // StackTrace stackTrace = new StackTrace(); // get call stack // StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) // // // write call stack method names // foreach (StackFrame stackFrame in stackFrames) // { // m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name)); // write method name // } // The below is far more useful // System.Console.WriteLine("------------------------------------------"); // System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); // System.Console.WriteLine("------------------------------------------"); // foreach (KeyValuePair<Thread, string> kvp in ReadLockers) // { // System.Console.WriteLine("Locker name {0} call stack:\n" + kvp.Value, kvp.Key.Name); // System.Console.WriteLine("------------------------------------------"); // } } catch { } m_itemLock.ExitReadLock(); } if (m_itemLock.RecursiveWriteCount > 0) { m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed."); // try // { // System.Console.WriteLine("------------------------------------------"); // System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); // System.Console.WriteLine("------------------------------------------"); // System.Console.WriteLine("Locker's call stack:\n" + WriterStack); // System.Console.WriteLine("------------------------------------------"); // } // catch // {} m_itemLock.ExitWriteLock(); } while (!m_itemLock.TryEnterReadLock(60000)) { m_log.Error("Thread lock detected while trying to aquire READ lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); //if (m_itemLock.IsWriteLockHeld) //{ m_itemLock = new System.Threading.ReaderWriterLockSlim(); // System.Console.WriteLine("------------------------------------------"); // System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); // System.Console.WriteLine("------------------------------------------"); // System.Console.WriteLine("Locker's call stack:\n" + WriterStack); // System.Console.WriteLine("------------------------------------------"); // LockedByThread = null; // ReadLockers.Clear(); //} } // ReadLockers[Thread.CurrentThread] = Environment.StackTrace; } else { if (m_itemLock.RecursiveReadCount > 0) { m_itemLock.ExitReadLock(); } // if (m_itemLock.RecursiveReadCount == 0) // ReadLockers.Remove(Thread.CurrentThread); } }