Avoid Dependencies In a library: Android

When providing a library like a parser for location-based information one of the most important points is to not create any kind of dependency into the application which later uses the library.
But what does this mean? Here is a small example:
The application ApplA wants to get the location for a certain GPS position and store it into an ApplA.LocationObject, so a request to the library would look like this:

 

 1: ApplA.LocationObject o= locationLib.getLocationFor(longitude,latitude);

 

And here is the problem why this is not the right way to do it: If someone else wants to use the library in another application B, this application would need the ApplA.LocationObject which it will not have access to. So the developer of application B would need to change the library code to return a ApplB.LocationObject and this would have to be done every time the library is imported into a new application. Often it not even possible to change the library code because it’s wrapped in a non editable jar-file so another solution has to be found.
The most obvious solution would be to move the LocationObject class into the library and return a Library.LocationObj for the request. Then a developer would need to use this LocationObj in his or her application or the information would have to be extracted from the Library.LocationObj and stored in a ApplA.LocationObj. This solution is not very flexible and will force the developer to be dependant on the objects it gets from the library or convert them at least. He has to determine what is stored in the Library.LocationObj and how to get access to this information.
Lets take a step back to what the developer would really want to get. It is information about the location at a certain GPS position so how do we return this information and not a static object where the developer has to figure out how to use it and get to the information inside. The answer to this question is the listener concept and here is how it works:
The user will pass an additional object (the listener) when requesting the location for the GPS position, so it will look like this:

 

 1: Library.LocationListener l = new ApplA.MyLocationObject();
 2: locationLib.getLocationFor(longitude,latitude, l);And the ApplA.MyLocationObject would have to look like this:
 3: class ApplA.MyLocationObject implements Library.LocationListener{
 4:  ...
 5:  public void onRecieveLocationInformation(String locName, String address, ...){
 6:   //store the received information
 7:  }
 8: }

 

The library then has to call the onRecieveLocationInformation-method when the information is parsed. This way the ApplA.MyLocationObject now only has to implement the LocationListener interface and it will be notified by the library when the location information is received. It will get all the information about the location and can store these in its custom way.
The listener concept is a very powerful way to remove dependencies and this is only one of many scenarios where it can be used. There are a lot more benefits when using this concept, for example this way the request to the server could be done in a separate thread much easier because the code is no longer structured in a linear way.
Here is one more example how your code could look like, when using the listener concept:

 

 1: final MyLocationObject o = new MyLocationObject();
 2: locationLib.getLocationFor(longitude,latitude, new Library.LocationListener(){
 3:  public void onRecieveLocationInformation(String locName, String address, ...){
 4:   //store the received information:
 5:   o.setName(locName);
 6:   o.setAddress(address);
 7:   addLocationToLocationList(o);
 8:  }
 9: });
 10: 
 11: ...
 12: 
 13: void addLocationToLocationList(o){
 14:  ...
 15: }

 

So what do you think about this? Feel free to add some comments Open-mouthed smile

Random Name Generator: Android

Today i needed a name generator so i wrote one myself (i didn’t like the existing ones i found via Google. Here is the test code i used:

   1:  NameGenerator gen = new NameGenerator();
   2:  for (int i = 0; i < 30; i++) { System.out.println(gen.getName()); } 

It produces names like:
Pausyp
Braurjnn
Thushoob
Einnjk
Qeidegh
Aub
Xoihut
Voopych
Gljint
Och
Stontaigh
Loofautt
Grennoogh
Jshjnt
Zjlouv
Fabeih
Aishof
Hoir
Ait
Jihoint
Aiv
Poim
Flott
Ustjv
Zjis
Xittoutt
I also added constructors for complete customization of the generate process. Here is the code:

   1:  public class NameGenerator {
   2:  private List vocals = new ArrayList();
   3:  private List startConsonants = new ArrayList();
   4:  private List endConsonants = new ArrayList();
   5:  private List nameInstructions = new ArrayList();
   6:  public NameGenerator() {
   7:  String demoVocals[] = { "a", "e", "i", "o", "u", "ei", "ai", "ou", "j",
   8:  "ji", "y", "oi", "au", "oo" };
   9:  String demoStartConsonants[] = { "b", "c", "d", "f", "g", "h", "k",
  10:  "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "z",
  11:  "ch", "bl", "br", "fl", "gl", "gr", "kl", "pr", "st", "sh",
  12:  "th" };
  13:  String demoEndConsonants[] = { "b", "d", "f", "g", "h", "k", "l", "m",
  14:  "n", "p", "r", "s", "t", "v", "w", "z", "ch", "gh", "nn", "st",
  15:  "sh", "th", "tt", "ss", "pf", "nt" };
  16:  String nameInstructions[] = { "vd", "cvdvd", "cvd", "vdvd" };
  17:  this.vocals.addAll(Arrays.asList(demoVocals));
  18:  this.startConsonants.addAll(Arrays.asList(demoStartConsonants));
  19:  this.endConsonants.addAll(Arrays.asList(demoEndConsonants));
  20:  this.nameInstructions.addAll(Arrays.asList(nameInstructions));
  21:  }
  22:  /**
  23:  * 
  24:  * The names will look like this
  25:  * (v=vocal,c=startConsonsonant,d=endConsonants): vd, cvdvd, cvd, vdvd
  26:  * 
  27:  * @param vocals
  28:  * pass something like {"a","e","ou",..}
  29:  * @param startConsonants
  30:  * pass something like {"s","f","kl",..}
  31:  * @param endConsonants
  32:  * pass something like {"th","sh","f",..}
  33:  */
  34:  public NameGenerator(String[] vocals, String[] startConsonants,
  35:  String[] endConsonants) {
  36:  this.vocals.addAll(Arrays.asList(vocals));
  37:  this.startConsonants.addAll(Arrays.asList(startConsonants));
  38:  this.endConsonants.addAll(Arrays.asList(endConsonants));
  39:  }
  40:  /**
  41:  * see {@link NameGenerator#NameGenerator(String[], String[], String[])}
  42:  * 
  43:  * @param vocals
  44:  * @param startConsonants
  45:  * @param endConsonants
  46:  * @param nameInstructions
  47:  * Use only the following letters:
  48:  * (v=vocal,c=startConsonsonant,d=endConsonants)! Pass something
  49:  * like {"vd", "cvdvd", "cvd", "vdvd"}
  50:  */
  51:  public NameGenerator(String[] vocals, String[] startConsonants,
  52:  String[] endConsonants, String[] nameInstructions) {
  53:  this(vocals, startConsonants, endConsonants);
  54:  this.nameInstructions.addAll(Arrays.asList(nameInstructions));
  55:  }
  56:  public String getName() {
  57:  return firstCharUppercase(getNameByInstructions(getRandomElementFrom(nameInstructions)));
  58:  }
  59:  private int randomInt(int min, int max) {
  60:  return (int) (min + (Math.random() * (max + 1 - min)));
  61:  }
  62:  private String getNameByInstructions(String nameInstructions) {
  63:  String name = "";
  64:  int l = nameInstructions.length();
  65:  for (int i = 0; i < l; i++) { char x = nameInstructions.charAt(0); switch (x) { case 'v': name += getRandomElementFrom(vocals); break; case 'c': name += getRandomElementFrom(startConsonants); break; case 'd': name += getRandomElementFrom(endConsonants); break; } nameInstructions = nameInstructions.substring(1); } return name; } private String firstCharUppercase(String name) { return Character.toString(name.charAt(0)).toUpperCase() + name.substring(1); } private String getRandomElementFrom(List v) {
  66:  return v.get(randomInt(0, v.size() - 1));
  67:  }
  68:  }

 

Comment Please.Rolling on the floor laughing

10 Rules Every Android Programmer Should Know

I’ve now read a few interesting things that you should consider when programming Android in order to ensure as much performance as possible:

  1. As rarely as possible allocate memory
  2. Possible use etc but no integer int.
  3. Temporary return values ​​to avoid if possible! Strings that are used once and then return to the no longer needed brakes, the system unnecessarily. Rather the operation on the string to move the method itself.
  4. Multidimensional arrays can be simulated by one dimensional. Rumgetrickse for me a bit too much at the expense of readability ..
  5. Virtual methods instead of interface methods (eg, not using hashmap Map)
  6. Static methods are much faster than virtual
  7. no getter and setter
  8. Instead of access to member variables, they should only pass to a local.
  9. Do not use enums but constants for the elements of enums
  10. Avoid use of floating point numbers as floating-point arithmetic must be simulates cumbersome.

    One has therefore to ensure the performance of a piece of code readability, reduce and rewrite in a few years, the unreadable code again.

c7875ff7f880fe46f6b3067ecc30a41a-server-clip-art

The advantage of threading is the ability to create applications that use more than one thread of execution. For example, a process can have a user interface thread that manages interactions with the user and worker threads that perform other tasks while the user interface thread waits for user input.

This tutorial demonstrates various thread activities:

  • Creating and executing a thread
  • Synchronization of threads
  • Interaction between threads
  • Using a thread pool
  • Using a mutex object to protect a shared resource
  • See Threading Sample to download and build the sample files discussed in this tutorial.

    Sample Files

     

    Example 1: Creating, starting, and interacting between threads

    This example demonstrates how to create and start a thread, and shows the interaction between two threads running simultaneously within the same process. Note that you don’t have to stop or free the thread. This is done automatically by the .NET Framework common language runtime.

    The program begins by creating an object of type Alpha (oAlpha) and a thread (oThread) that references the Beta method of the Alpha class. The thread is then started. TheIsAlive property of the thread allows the program to wait until the thread is initialized (created, allocated, and so on). The main thread is accessed through Thread, and theSleep method tells the thread to give up its time slice and stop executing for a certain amount of milliseconds. The oThread is then stopped and joined. Joining a thread makes the main thread wait for it to die or for a specified time to expire (for more details, see Thread.Join Method). Finally, the program attempts to restart oThread, but fails because a thread cannot be restarted after it is stopped (aborted). For information on temporary cessation of execution, see Suspending Thread Execution.

       1:  // StopJoin.cs
       2:  using System;
       3:  using System.Threading;
       4:   
       5:  public class Alpha
       6:  {
       7:   
       8:     // This method that will be called when the thread is started
       9:     public void Beta()
      10:     {
      11:        while (true)
      12:        {
      13:           Console.WriteLine("Alpha.Beta is running in its own thread.");
      14:        }
      15:     }
      16:  };
      17:   
      18:  public class Simple
      19:  {
      20:     public static int Main()
      21:     {
      22:        Console.WriteLine("Thread Start/Stop/Join Sample");
      23:        
      24:        Alpha oAlpha = new Alpha();
      25:   
      26:        // Create the thread object, passing in the Alpha.Beta method
      27:        // via a ThreadStart delegate. This does not start the thread.
      28:        Thread oThread = new Thread(new ThreadStart(oAlpha.Beta));
      29:   
      30:        // Start the thread
      31:        oThread.Start();
      32:   
      33:        // Spin for a while waiting for the started thread to become
      34:        // alive:
      35:        while (!oThread.IsAlive);
      36:        
      37:        // Put the Main thread to sleep for 1 millisecond to allow oThread
      38:        // to do some work:
      39:        Thread.Sleep(1);
      40:        
      41:        // Request that oThread be stopped
      42:        oThread.Abort();
      43:        
      44:        // Wait until oThread finishes. Join also has overloads
      45:        // that take a millisecond interval or a TimeSpan object.
      46:        oThread.Join();
      47:        
      48:        Console.WriteLine();
      49:        Console.WriteLine("Alpha.Beta has finished");
      50:        
      51:        try 
      52:        {
      53:           Console.WriteLine("Try to restart the Alpha.Beta thread");
      54:           oThread.Start();
      55:        }
      56:        catch (ThreadStateException) 
      57:        {
      58:           Console.Write("ThreadStateException trying to restart Alpha.Beta. ");
      59:           Console.WriteLine("Expected since aborted threads cannot be restarted.");
      60:        }
      61:        return 0;
      62:     }
      63:  }

    Example Output

    Thread Start/Stop/Join Sample
    Alpha.Beta is running in its own thread.
    Alpha.Beta is running in its own thread.
    Alpha.Beta is running in its own thread.
    ...
    ...
    Alpha.Beta has finished
    Try to restart the Alpha.Beta thread
    ThreadStateException trying to restart Alpha.Beta. Expected since aborted threads cannot be restarted.
    

    Example 2: Synchronizing two threads: a producer and a consumer

    The following example shows how synchronization can be accomplished using the C# lock keyword and the Pulse method of the Monitor object. The Pulse method notifies a thread in the waiting queue of a change in the object’s state (for more details on pulses, see the Monitor.Pulse Method).

    The example creates a Cell object that has two methods: ReadFromCell and WriteToCell. Two other objects are created from classes CellProd and CellCons; these objects both have a method ThreadRun whose job is to call ReadFromCell and WriteToCell. Synchronization is accomplished by waiting for “pulses” from the Monitor object, which come in order. That is, first an item is produced (the consumer at this point is waiting for a pulse), then a pulse occurs, then the consumer consumes the production (while the producer is waiting for a pulse), and so on.

       1:  // MonitorSample.cs
       2:  // This example shows use of the following methods of the C# lock keyword
       3:  // and the Monitor class 
       4:  // in threads:
       5:  //      Monitor.Pulse(Object)
       6:  //      Monitor.Wait(Object)
       7:  using System;
       8:  using System.Threading;
       9:   
      10:  public class MonitorSample
      11:  {
      12:     public static void Main(String[] args)
      13:     {
      14:        int result = 0;   // Result initialized to say there is no error
      15:        Cell cell = new Cell( );
      16:   
      17:        CellProd prod = new CellProd(cell, 20);  // Use cell for storage, 
      18:                                                 // produce 20 items
      19:        CellCons cons = new CellCons(cell, 20);  // Use cell for storage, 
      20:                                                 // consume 20 items
      21:   
      22:        Thread producer = new Thread(new ThreadStart(prod.ThreadRun));
      23:        Thread consumer = new Thread(new ThreadStart(cons.ThreadRun));
      24:        // Threads producer and consumer have been created, 
      25:        // but not started at this point.
      26:   
      27:        try
      28:        {
      29:           producer.Start( );
      30:           consumer.Start( );
      31:   
      32:           producer.Join( );   // Join both threads with no timeout
      33:                               // Run both until done.
      34:           consumer.Join( );  
      35:        // threads producer and consumer have finished at this point.
      36:        }
      37:        catch (ThreadStateException e)
      38:        {
      39:           Console.WriteLine(e);  // Display text of exception
      40:           result = 1;            // Result says there was an error
      41:        }
      42:        catch (ThreadInterruptedException e)
      43:        {
      44:           Console.WriteLine(e);  // This exception means that the thread
      45:                                  // was interrupted during a Wait
      46:           result = 1;            // Result says there was an error
      47:        }
      48:        // Even though Main returns void, this provides a return code to 
      49:        // the parent process.
      50:        Environment.ExitCode = result;
      51:     }
      52:  }
      53:   
      54:  public class CellProd
      55:  {
      56:     Cell cell;         // Field to hold cell object to be used
      57:     int quantity = 1;  // Field for how many items to produce in cell
      58:   
      59:     public CellProd(Cell box, int request)
      60:     {
      61:        cell = box;          // Pass in what cell object to be used
      62:        quantity = request;  // Pass in how many items to produce in cell
      63:     }
      64:     public void ThreadRun( )
      65:     {
      66:        for(int looper=1; looper<=quantity; looper++)
      67:           cell.WriteToCell(looper);  // "producing"
      68:     }
      69:  }
      70:   
      71:  public class CellCons
      72:  {
      73:     Cell cell;         // Field to hold cell object to be used
      74:     int quantity = 1;  // Field for how many items to consume from cell
      75:   
      76:     public CellCons(Cell box, int request)
      77:     {
      78:        cell = box;          // Pass in what cell object to be used
      79:        quantity = request;  // Pass in how many items to consume from cell
      80:     }
      81:     public void ThreadRun( )
      82:     {
      83:        int valReturned;
      84:        for(int looper=1; looper<=quantity; looper++)
      85:        // Consume the result by placing it in valReturned.
      86:           valReturned=cell.ReadFromCell( );
      87:     }
      88:  }
      89:   
      90:  public class Cell
      91:  {
      92:     int cellContents;         // Cell contents
      93:     bool readerFlag = false;  // State flag
      94:     public int ReadFromCell( )
      95:     {
      96:        lock(this)   // Enter synchronization block
      97:        {
      98:           if (!readerFlag)
      99:           {            // Wait until Cell.WriteToCell is done producing
     100:              try
     101:              {
     102:                 // Waits for the Monitor.Pulse in WriteToCell
     103:                 Monitor.Wait(this);
     104:              }
     105:              catch (SynchronizationLockException e)
     106:              {
     107:                 Console.WriteLine(e);
     108:              }
     109:              catch (ThreadInterruptedException e)
     110:              {
     111:                 Console.WriteLine(e);
     112:              }
     113:           }
     114:           Console.WriteLine("Consume: {0}",cellContents);
     115:           readerFlag = false;    // Reset the state flag to say consuming
     116:                                  // is done.
     117:           Monitor.Pulse(this);   // Pulse tells Cell.WriteToCell that
     118:                                  // Cell.ReadFromCell is done.
     119:        }   // Exit synchronization block
     120:        return cellContents;
     121:     }
     122:     
     123:     public void WriteToCell(int n)
     124:     {
     125:        lock(this)  // Enter synchronization block
     126:        {
     127:           if (readerFlag)
     128:           {      // Wait until Cell.ReadFromCell is done consuming.
     129:              try
     130:              {
     131:                 Monitor.Wait(this);   // Wait for the Monitor.Pulse in
     132:                                       // ReadFromCell
     133:              }
     134:              catch (SynchronizationLockException e)
     135:              {
     136:                 Console.WriteLine(e);
     137:              }
     138:              catch (ThreadInterruptedException e)
     139:              {
     140:                 Console.WriteLine(e);
     141:              }
     142:           }
     143:           cellContents = n;
     144:           Console.WriteLine("Produce: {0}",cellContents);
     145:           readerFlag = true;    // Reset the state flag to say producing
     146:                                 // is done
     147:           Monitor.Pulse(this);  // Pulse tells Cell.ReadFromCell that 
     148:                                 // Cell.WriteToCell is done.
     149:        }   // Exit synchronization block
     150:     }
     151:  }
    Example Output
    Produce: 1
    Consume: 1
    Produce: 2
    Consume: 2
    Produce: 3
    Consume: 3
    ...
    ...
    Produce: 20
    Consume: 20
    

     

    Example 3: Using a thread pool

    The following example shows how to use a thread pool. It first creates a ManualResetEvent object, which enables the program to know when the thread pool has finished running all of the work items. Next, it attempts to add one thread to the thread pool. If this succeeds, it adds the rest (four in this example). The thread pool will then put work items into available threads. The WaitOne method on eventX is called, which causes the rest of the program to wait until the event is triggered (with the eventX.Set method). Finally, the program prints out the load (the thread that actually executes a particular work item) on the threads.

       1:  // SimplePool.cs
       2:  // Simple thread pool example
       3:  using System;
       4:  using System.Collections;
       5:  using System.Threading;
       6:   
       7:  // Useful way to store info that can be passed as a state on a work item
       8:  public class SomeState
       9:  {
      10:     public int Cookie;
      11:     public SomeState(int iCookie)
      12:     {
      13:        Cookie = iCookie;
      14:     }
      15:  }
      16:   
      17:  public class Alpha
      18:  {
      19:     public Hashtable HashCount;
      20:     public ManualResetEvent eventX;
      21:     public static int iCount = 0;
      22:     public static int iMaxCount = 0;
      23:     public Alpha(int MaxCount) 
      24:     {
      25:        HashCount = new Hashtable(MaxCount);
      26:        iMaxCount = MaxCount;
      27:     }
      28:   
      29:     // Beta is the method that will be called when the work item is
      30:     // serviced on the thread pool.
      31:     // That means this method will be called when the thread pool has
      32:     // an available thread for the work item.
      33:     public void Beta(Object state)
      34:     {
      35:        // Write out the hashcode and cookie for the current thread
      36:        Console.WriteLine(" {0} {1} :", Thread.CurrentThread.GetHashCode(),
      37:           ((SomeState)state).Cookie);
      38:        // The lock keyword allows thread-safe modification
      39:        // of variables accessible across multiple threads.
      40:        Console.WriteLine(
      41:           "HashCount.Count=={0}, Thread.CurrentThread.GetHashCode()=={1}",
      42:           HashCount.Count, 
      43:           Thread.CurrentThread.GetHashCode());
      44:        lock (HashCount) 
      45:        {
      46:           if (!HashCount.ContainsKey(Thread.CurrentThread.GetHashCode()))
      47:              HashCount.Add (Thread.CurrentThread.GetHashCode(), 0);
      48:           HashCount[Thread.CurrentThread.GetHashCode()] = 
      49:              ((int)HashCount[Thread.CurrentThread.GetHashCode()])+1;
      50:        }
      51:   
      52:        // Do some busy work.
      53:        // Note: Depending on the speed of your machine, if you 
      54:        // increase this number, the dispersement of the thread
      55:        // loads should be wider.
      56:        int iX  = 2000;
      57:        Thread.Sleep(iX);
      58:        // The Interlocked.Increment method allows thread-safe modification
      59:        // of variables accessible across multiple threads.
      60:        Interlocked.Increment(ref iCount);
      61:        if (iCount == iMaxCount)
      62:        {
      63:           Console.WriteLine();
      64:           Console.WriteLine("Setting eventX ");
      65:           eventX.Set();
      66:        }
      67:     }
      68:  }
      69:   
      70:  public class SimplePool
      71:  {
      72:     public static int Main(string[] args)
      73:     {
      74:        Console.WriteLine("Thread Pool Sample:");
      75:        bool W2K = false;
      76:        int MaxCount = 10;  // Allow a total of 10 threads in the pool
      77:        // Mark the event as unsignaled.
      78:        ManualResetEvent eventX = new ManualResetEvent(false);
      79:        Console.WriteLine("Queuing {0} items to Thread Pool", MaxCount);
      80:        Alpha oAlpha = new Alpha(MaxCount);  // Create the work items.
      81:        // Make sure the work items have a reference to the signaling event.
      82:        oAlpha.eventX = eventX;
      83:        Console.WriteLine("Queue to Thread Pool 0");
      84:        try
      85:        {
      86:           // Queue the work items, which has the added effect of checking
      87:           // which OS is running.
      88:           ThreadPool.QueueUserWorkItem(new WaitCallback(oAlpha.Beta),
      89:              new SomeState(0));
      90:           W2K = true;
      91:        }
      92:        catch (NotSupportedException)
      93:        {
      94:           Console.WriteLine("These API's may fail when called on a non-Windows 2000 system.");
      95:           W2K = false;
      96:        }
      97:        if (W2K)  // If running on an OS which supports the ThreadPool methods.
      98:        {
      99:           for (int iItem=1;iItem < MaxCount;iItem++)
     100:           {
     101:              // Queue the work items:
     102:              Console.WriteLine("Queue to Thread Pool {0}", iItem);
     103:              ThreadPool.QueueUserWorkItem(new WaitCallback(oAlpha.Beta),new SomeState(iItem));
     104:           }
     105:           Console.WriteLine("Waiting for Thread Pool to drain");
     106:           // The call to exventX.WaitOne sets the event to wait until
     107:           // eventX.Set() occurs.
     108:           // (See oAlpha.Beta).
     109:           // Wait until event is fired, meaning eventX.Set() was called:
     110:           eventX.WaitOne(Timeout.Infinite,true);
     111:           // The WaitOne won't return until the event has been signaled.
     112:           Console.WriteLine("Thread Pool has been drained (Event fired)");
     113:           Console.WriteLine();
     114:           Console.WriteLine("Load across threads");
     115:           foreach(object o in oAlpha.HashCount.Keys)
     116:              Console.WriteLine("{0} {1}", o, oAlpha.HashCount[o]);
     117:        }
     118:        return 0;
     119:     }
     120:  }

    Example Output

    Note The following output will vary from one computer to another.

    Thread Pool Sample:
    Queuing 10 items to Thread Pool
    Queue to Thread Pool 0
    Queue to Thread Pool 1
    ...
    ...
    Queue to Thread Pool 9
    Waiting for Thread Pool to drain
     98 0 :
    HashCount.Count==0, Thread.CurrentThread.GetHashCode()==98
     100 1 :
    HashCount.Count==1, Thread.CurrentThread.GetHashCode()==100
     98 2 :
    ...
    ...
    Setting eventX
    Thread Pool has been drained (Event fired)
    
    Load across threads
    101 2
    100 3
    98 4
    102 1
    

    Example 4: Using the Mutex object

    You can use a mutex object to protect a shared resource from simultaneous access by multiple threads or processes. The state of a mutex object is either set to signaled, when it is not owned by any thread, or nonsignaled, when it is owned. Only one thread at a time can own a mutex object. For example, to prevent two threads from writing to shared memory at the same time, each thread waits for ownership of a mutex object before executing the code that accesses the memory. After writing to the shared memory, the thread releases the mutex object.

    This example demonstrates how to use the classes Mutex, AutoResetEvent, and WaitHandle in processing threads. It also demonstrates the methods used in processing the mutex object.

       1:  // Mutex.cs
       2:  // Mutex object example
       3:  using System;
       4:  using System.Threading;
       5:   
       6:  public class MutexSample
       7:  {
       8:     static Mutex gM1;
       9:     static Mutex gM2;
      10:     const int ITERS = 100;
      11:     static AutoResetEvent Event1 = new AutoResetEvent(false);
      12:     static AutoResetEvent Event2 = new AutoResetEvent(false);
      13:     static AutoResetEvent Event3 = new AutoResetEvent(false);
      14:     static AutoResetEvent Event4 = new AutoResetEvent(false);
      15:     
      16:     public static void Main(String[] args)
      17:     {
      18:        Console.WriteLine("Mutex Sample ...");
      19:        // Create Mutex initialOwned, with name of "MyMutex".
      20:        gM1 = new Mutex(true,"MyMutex");
      21:        // Create Mutex initialOwned, with no name.
      22:        gM2 = new Mutex(true);
      23:        Console.WriteLine(" - Main Owns gM1 and gM2");
      24:   
      25:        AutoResetEvent[] evs = new AutoResetEvent[4];
      26:        evs[0] = Event1;    // Event for t1
      27:        evs[1] = Event2;    // Event for t2
      28:        evs[2] = Event3;    // Event for t3
      29:        evs[3] = Event4;    // Event for t4
      30:   
      31:        MutexSample tm = new MutexSample( );
      32:        Thread t1 = new Thread(new ThreadStart(tm.t1Start));
      33:        Thread t2 = new Thread(new ThreadStart(tm.t2Start));
      34:        Thread t3 = new Thread(new ThreadStart(tm.t3Start));
      35:        Thread t4 = new Thread(new ThreadStart(tm.t4Start));
      36:        t1.Start( );   // Does Mutex.WaitAll(Mutex[] of gM1 and gM2)
      37:        t2.Start( );   // Does Mutex.WaitOne(Mutex gM1)
      38:        t3.Start( );   // Does Mutex.WaitAny(Mutex[] of gM1 and gM2)
      39:        t4.Start( );   // Does Mutex.WaitOne(Mutex gM2)
      40:   
      41:        Thread.Sleep(2000);
      42:        Console.WriteLine(" - Main releases gM1");
      43:        gM1.ReleaseMutex( );  // t2 and t3 will end and signal
      44:   
      45:        Thread.Sleep(1000);
      46:        Console.WriteLine(" - Main releases gM2");
      47:        gM2.ReleaseMutex( );  // t1 and t4 will end and signal
      48:   
      49:        // Waiting until all four threads signal that they are done.
      50:        WaitHandle.WaitAll(evs); 
      51:        Console.WriteLine("... Mutex Sample");
      52:     }
      53:   
      54:     public void t1Start( )
      55:     {
      56:        Console.WriteLine("t1Start started,  Mutex.WaitAll(Mutex[])");
      57:        Mutex[] gMs = new Mutex[2];
      58:        gMs[0] = gM1;  // Create and load an array of Mutex for WaitAll call
      59:        gMs[1] = gM2;
      60:        Mutex.WaitAll(gMs);  // Waits until both gM1 and gM2 are released
      61:        Thread.Sleep(2000);
      62:        Console.WriteLine("t1Start finished, Mutex.WaitAll(Mutex[]) satisfied");
      63:        Event1.Set( );      // AutoResetEvent.Set() flagging method is done
      64:     }
      65:   
      66:     public void t2Start( )
      67:     {
      68:        Console.WriteLine("t2Start started,  gM1.WaitOne( )");
      69:        gM1.WaitOne( );    // Waits until Mutex gM1 is released
      70:        Console.WriteLine("t2Start finished, gM1.WaitOne( ) satisfied");
      71:        Event2.Set( );     // AutoResetEvent.Set() flagging method is done
      72:     }
      73:   
      74:     public void t3Start( )
      75:     {
      76:        Console.WriteLine("t3Start started,  Mutex.WaitAny(Mutex[])");
      77:        Mutex[] gMs = new Mutex[2];
      78:        gMs[0] = gM1;  // Create and load an array of Mutex for WaitAny call
      79:        gMs[1] = gM2;
      80:        Mutex.WaitAny(gMs);  // Waits until either Mutex is released
      81:        Console.WriteLine("t3Start finished, Mutex.WaitAny(Mutex[])");
      82:        Event3.Set( );       // AutoResetEvent.Set() flagging method is done
      83:     }
      84:   
      85:     public void t4Start( )
      86:     {
      87:        Console.WriteLine("t4Start started,  gM2.WaitOne( )");
      88:        gM2.WaitOne( );   // Waits until Mutex gM2 is released
      89:        Console.WriteLine("t4Start finished, gM2.WaitOne( )");
      90:        Event4.Set( );    // AutoResetEvent.Set() flagging method is done
      91:     }
      92:  }

    Sample Output

    Mutex Sample ...
     - Main Owns gM1 and gM2
    t1Start started,  Mutex.WaitAll(Mutex[])
    t2Start started,  gM1.WaitOne( )
    t3Start started,  Mutex.WaitAny(Mutex[])
    t4Start started,  gM2.WaitOne( )
     - Main releases gM1
    t2Start finished, gM1.WaitOne( ) satisfied
    t3Start finished, Mutex.WaitAny(Mutex[])
     - Main releases gM2
    t1Start finished, Mutex.WaitAll(Mutex[]) satisfied
    t4Start finished, gM2.WaitOne( )
    ... Mutex Sample