Home Page
  • December 11, 2024, 04:00:39 am *
  • Welcome, Guest
Please login or register.

Login with username, password and session length
Advanced search  

News:

Official site launch very soon, hurrah!



Post reply

Warning: this topic has not been posted in for at least 120 days.
Unless you're sure you want to reply, please consider starting a new topic.

Note: this post will not display until it's been approved by a moderator.

Name:
Email:
Subject:
Message icon:

Attach:
(Clear Attachment)
(more attachments)
Restrictions: 10 per post, maximum total size 8192KB, maximum individual size 5120KB
Note that any files attached will not be displayed until approved by a moderator.
Verification:
Type the letters shown in the picture
Listen to the letters / Request another image

Type the letters shown in the picture:
Please stop spamming. Your spam posts are moderated and will never be displayed on the internet. What is eighty-eight minus eighty-six (spell out the answer):
Пожалуйста, прекратите спамить. Ваши спам-сообщения модерируются и никогда не будут отображаться в Интернете. What color is grass.:

shortcuts: hit alt+s to submit/post or alt+p to preview


Topic Summary

Posted by: Dakusan
« on: January 09, 2013, 11:18:00 pm »

Original post for Thread synchronization in C# can be found at https://www.castledragmire.com/Posts/Thread_synchronization_in_C%23.
Originally posted on: 01/09/13

I have been working heavily in C# CE (Compact Edition) v2.0 for the last 2 years for clients, and one of the very many things that I was never really happy with (in at least that version of the language, though it looks like it might plague all versions of C#) is the available thread synchronization tools. I’ve come to love the lock/wait/notify model (in Java it’s synchronized/wait/notify and in Perl it’s lock/cond_wait/cond_signal), but I have found nothing as intuitive and safe to use in C#. To alleviate this, I went ahead and wrote my own ThreadLockAndWait class that achieves this functionality.


This works the same as the POSIX lock, unlock, cond_wait, cond_signal, and cond_timedwait functions, except:
  • Lock is not required before CondSignal (it does its own inner lock and unlock)
  • If ReacquireLockAfterWait is false, in which case CondWait will not lock again after signaled and just continue immediately
  • Only 1 thread can be CondWaiting at a time (If one is CondWaiting and is signaled but not reacquired the lock, its ok for another to start CondWaiting)


public class ThreadLockAndWait
{
   private Mutex TheLock=new Mutex(), CondWaitLock=new Mutex(); //CondWaitLock makes sure 1 thread stops waiting before the next one starts waiting
   private ManualResetEvent WaitTimer=new ManualResetEvent(false);
   private string OwnersThreadName=null;
   private int OwnerLockCount=0;

   public void Lock()
   {
      TheLock.WaitOne();
      if(OwnerLockCount++==0)
         OwnersThreadName=Thread.CurrentThread.Name;
   }
   public void UnLock()
   {
      TheLock.WaitOne();
      if(OwnerLockCount==0)
      {
         TheLock.ReleaseMutex();
         throw new Exception("Cannot unlock if not locked");
      }
      TheLock.ReleaseMutex();
      if(--OwnerLockCount==0)
         OwnersThreadName=null;
      TheLock.ReleaseMutex();
   }
   public void CondWait() { RealCondWait(-1, true); }
   public void CondWait(bool ReacquireLockAfterWait) { RealCondWait(-1, ReacquireLockAfterWait); }
   public void CondTimedWait(int TimeToWait) { RealCondWait(Math.Max(0, TimeToWait), true); }
   public void CondTimedWait(int TimeToWait, bool ReacquireLockAfterWait) { RealCondWait(Math.Max(0, TimeToWait), ReacquireLockAfterWait); }
   private void RealCondWait(int TimeToWait, bool ReacquireLockAfterWait)
   {
      //Prepare to wait
      TheLock.WaitOne();
      if(OwnerLockCount==0)
      {
         TheLock.ReleaseMutex();
         throw new Exception("Cannot wait if not locked");
      }
      CondWaitLock.WaitOne(); //Release this wait before the next one starts
      WaitTimer.Reset();
      TheLock.ReleaseMutex();

      //Release all locks
      int PreviousLockCount=OwnerLockCount;
      OwnersThreadName=null;
      OwnerLockCount=0;
      if(PreviousLockCount!=1)
         System.Diagnostics.Debug.Print("Warning, mutex has multiple locks from thread!");
      for(int i=0;i<PreviousLockCount;i++)
         TheLock.ReleaseMutex();

      //Wait
      if(TimeToWait>0)
         WaitTimer.WaitOne(TimeToWait, false);
      else if(TimeToWait!=0)
         WaitTimer.WaitOne();
      CondWaitLock.ReleaseMutex();

      //Reacquire lock
      if(!ReacquireLockAfterWait)
         return;
      for(int i=0;i<PreviousLockCount;i++)
         TheLock.WaitOne();
      OwnerLockCount=PreviousLockCount;
      OwnersThreadName=Thread.CurrentThread.Name;
   }

   public void CondSignal()
   {
      TheLock.WaitOne();
      WaitTimer.Set();
      TheLock.ReleaseMutex();
   }
}