764
Part II: Exploring the C# Library
class IncThread {
int num;
public Thread Thrd;
public IncThread(string name, int n) {
Thrd = new Thread(this.Run);
num = n;
Thrd.Name = name;
Thrd.Start();
}
// Entry point of thread.
void Run() {
Console.WriteLine(Thrd.Name + " is waiting for the mutex.");
// Acquire the Mutex.
SharedRes.Mtx.WaitOne();
Console.WriteLine(Thrd.Name + " acquires the mutex.");
do {
Thread.Sleep(500);
SharedRes.Count++;
Console.WriteLine("In " + Thrd.Name +
", SharedRes.Count is " + SharedRes.Count);
num--;
} while(num > 0);
Console.WriteLine(Thrd.Name + " releases the mutex.");
// Release the Mutex.
SharedRes.Mtx.ReleaseMutex();
}
}
// This thread decrements SharedRes.Count.
class DecThread {
int num;
public Thread Thrd;
public DecThread(string name, int n) {
Thrd = new Thread(new ThreadStart(this.Run));
num = n;
Thrd.Name = name;
Thrd.Start();
}
// Entry point of thread.
void Run() {
Console.WriteLine(Thrd.Name + " is waiting for the mutex.");
Pdf split and merge - Merge, append PDF files in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
Provide C# Demo Codes for Merging and Appending PDF Document
merge pdf online; break pdf file into multiple files
Pdf split and merge - VB.NET PDF File Merge Library: Merge, append PDF files in vb.net, ASP.NET, MVC, Ajax, WinForms, WPF
VB.NET Guide and Sample Codes to Merge PDF Documents in .NET Project
reader combine pdf pages; reader merge pdf
P
A
R
T
I
I
Chapter 23: Multithreaded Programming, Part One  
765
// Acquire the Mutex.
SharedRes.Mtx.WaitOne();
Console.WriteLine(Thrd.Name + " acquires the mutex.");
do {
Thread.Sleep(500);
SharedRes.Count--;
Console.WriteLine("In " + Thrd.Name +
", SharedRes.Count is " + SharedRes.Count);
num--;
} while(num > 0);
Console.WriteLine(Thrd.Name + " releases the mutex.");
// Release the Mutex.
SharedRes.Mtx.ReleaseMutex();
}
}
class MutexDemo {
static void Main() {
// Construct three threads.
IncThread mt1 = new IncThread("Increment Thread", 5);
Thread.Sleep(1); // let the Increment thread start
DecThread mt2 = new DecThread("Decrement Thread", 5);
mt1.Thrd.Join();
mt2.Thrd.Join();
}
}
The output is shown here:
Increment Thread is waiting for the mutex.
Increment Thread acquires the mutex.
Decrement Thread is waiting for the mutex.
In Increment Thread, SharedRes.Count is 1
In Increment Thread, SharedRes.Count is 2
In Increment Thread, SharedRes.Count is 3
In Increment Thread, SharedRes.Count is 4
In Increment Thread, SharedRes.Count is 5
Increment Thread releases the mutex.
Decrement Thread acquires the mutex.
In Decrement Thread, SharedRes.Count is 4
In Decrement Thread, SharedRes.Count is 3
In Decrement Thread, SharedRes.Count is 2
In Decrement Thread, SharedRes.Count is 1
In Decrement Thread, SharedRes.Count is 0
Decrement Thread releases the mutex.
C# PDF File Split Library: Split, seperate PDF into multiple files
PDF ›› C# PDF: Split PDF. C# PDF - Split PDF Document in C#.NET. Explain How to Split PDF Document in Visual C#.NET Application. C# DLLs: Split PDF Document.
apple merge pdf; all jpg to one pdf converter
VB.NET PDF File Split Library: Split, seperate PDF into multiple
File: Split PDF Document. |. Home ›› XDoc.PDF ›› VB.NET PDF: Split PDF. VB.NET PDF - Split PDF Document Using VB.NET. VB.NET
pdf combine pages; pdf mail merge
766
Part II: Exploring the C# Library
As the output shows, access to SharedRes.Countis synchronized, with only one thread at a 
time being able to change its value.
To prove that the Mtx mutex was needed to produce the preceding output, try 
commenting out the calls to WaitOne( ) and ReleaseMutex( ) in the preceding program. 
When you run the program, you will see the following sequence (the actual output you see 
may vary):
In Increment Thread, SharedRes.Count is 1
In Decrement Thread, SharedRes.Count is 0
In Increment Thread, SharedRes.Count is 1
In Decrement Thread, SharedRes.Count is 0
In Increment Thread, SharedRes.Count is 1
In Decrement Thread, SharedRes.Count is 0
In Increment Thread, SharedRes.Count is 1
In Decrement Thread, SharedRes.Count is 0
In Increment Thread, SharedRes.Count is 1
As this output shows, without the mutex, increments and decrements to SharedRes.Count
are interspersed rather than sequenced.
The mutex created by the previous example is known only to the process that creates it. 
However, it is possible to create a mutex that is known systemwide. To do so, you must 
create a named mutex, using one of these constructors:
public Mutex(bool initiallyOwned, string name)
public Mutex(bool initiallyOwned, string name, out bool createdNew)
In both forms, the name of the mutex is passed in name. In the first form, if initiallyOwned
istrue, then ownership of the mutex is requested. However, because a systemwide mutex 
might already be owned by another process, it is better to specify false for this parameter. 
In the second form, on return createdNew will be true if ownership was requested and 
acquired. It will be false if ownership was denied. (There is also a third form of the Mutex
constructor that allows you to specify a MutexSecurity object, which controls access.) Using 
a named mutex enables you to manage interprocess synchronization.
One other point: It is legal for a thread that has acquired a mutex to make one or more 
additional calls to WaitOne( ) prior to calling ReleaseMutex( ), and these additional calls 
will succeed. That is, redundant calls to WaitOne( ) will not block a thread that already 
owns the mutex. However, the number of calls to WaitOne( ) must be balanced by the 
same number of calls to ReleaseMutex( ) before the mutex is released.
The Semaphore
A semaphore is similar to a mutex except that it can grant more than one thread access 
to a shared resource at the same time. Thus, the semaphore is useful when a collection of 
resources is being synchronized. A semaphore controls access to a shared resource through 
the use of a counter. If the counter is greater than zero, then access is allowed. If it is zero, 
access is denied. What the counter is counting are permits.Thus, to access the resource, a 
thread must be granted a permit from the semaphore.
In general, to use a semaphore, the thread that wants access to the shared resource tries 
to acquire a permit. If the semaphore’s counter is greater than zero, the thread acquires a 
permit, which causes the semaphore’s count to be decremented. Otherwise, the thread will 
block until a permit can be acquired. When the thread no longer needs access to the shared 
C# PDF: C#.NET PDF Document Merging & Splitting Control SDK
C# PDF - Merge or Split PDF File in C#.NET. C#.NET Code Demos to Combine or Divide Source PDF Document File. Visual C#. VB.NET. Home
pdf merger; combine pdfs online
VB.NET PDF: Use VB.NET Code to Merge and Split PDF Documents
VB.NET PDF - How to Merge and Split PDF. How to Merge and Split PDF Documents by Using VB.NET Code. Visual C#. VB.NET. Home > .NET Imaging
append pdf; c# pdf merge
P
A
R
T
I
I
Chapter 23: Multithreaded Programming, Part One  
767
resource, it releases the permit, which causes the semaphore’s count to be incremented. If 
there is another thread waiting for a permit, then that thread will acquire a permit at that 
e is 
created. If you create a semaphore that allows only one access, then a semaphore acts just 
like a mutex.
Semaphores are especially useful in situations in which a shared resource consists of a 
group or pool.
for communication, is a resource pool. A thread needing a network connection doesn’t care 
which one it gets. In this case, a semaphore offers a convenient mechanism to manage 
access to the connections.
The semaphore is implemented by System.Threading.Semaphore. It has several 
constructors. The simplest form is shown here:
public Semaphore(int initialCount, int maximumCount)
Here, initialCount specifies the initial value of the semaphore permit counter, which is the 
maximumCount.
Thus,maximumCount represents the maximum number of permits that can granted by the 
semaphore. The value in initialCount specifies how many of these permits are initially 
available.
Using a semaphore is similar to using a mutex, described earlier. To acquire access, your 
code will call WaitOne( ) on the semaphore. This method is inherited by Semaphore from 
theWaitHandle class.WaitOne( ) waits until the semaphore on which it is called can be 
acquired. Thus, it blocks execution of the calling thread until the specified semaphore can 
grant permission.
When your code no longer needs ownership of the semaphore, it releases it by calling 
Release( ), which is shown here:
public int Release( )
public int Release(int releaseCount)
The first form releases one permit. The second form releases the number of permits 
specified by releaseCount. Both return the permit count that existed prior to the release.
It is possible for a thread to call WaitOne( ) more than once before calling Release( ).
However, the number of calls to WaitOne( ) must be balanced by the same number of calls 
toRelease( ) before the permit is released. Alternatively, you can call the Release(int) form, 
passing a number equal to the number of times that WaitOne( ) was called.
Here is an example that illustrates the semaphore. In the program, the class MyThread
uses a semaphore to allow only two MyThread threads to be executed at any one time. 
Thus, the resource being shared is the CPU.
// Use a Semaphore.
using System;
using System.Threading;
// This thread allows only two instances of itself
// to run at any one time.
class MyThread {
public Thread Thrd;
VB.NET TIFF: Merge and Split TIFF Documents with RasterEdge .NET
Merge certain pages from different TIFF documents and create a &ltsummary> ''' Split a TIFF provide powerful & profession imaging controls, PDF document, tiff
break pdf into multiple files; acrobat split pdf into multiple files
VB.NET PDF Library SDK to view, edit, convert, process PDF file
Tell VB.NET users how to: create a new PDF file and load PDF from other file formats; merge, append, and split PDF files; insert, delete, move, rotate, copy
batch merge pdf; c# merge pdf pages
768
Part II: Exploring the C# Library
// This creates a semaphore that allows up to two
// permits to be granted and that initially has
// two permits available.
static Semaphore sem = new Semaphore(2, 2);
public MyThread(string name) {
Thrd = new Thread(this.Run);
Thrd.Name = name;
Thrd.Start();
}
// Entry point of thread.
void Run() {
Console.WriteLine(Thrd.Name + " is waiting for a permit.");
sem.WaitOne();
Console.WriteLine(Thrd.Name + " acquires a permit.");
for(char ch='A'; ch < 'D'; ch++) {
Console.WriteLine(Thrd.Name + " : " + ch + " ");
Thread.Sleep(500);
}
Console.WriteLine(Thrd.Name + " releases a permit.");
// Release the semaphore.
sem.Release();
}
}
class SemaphoreDemo {
static void Main() {
// Construct three threads.
MyThread mt1 = new MyThread("Thread #1");
MyThread mt2 = new MyThread("Thread #2");
MyThread mt3 = new MyThread("Thread #3");
mt1.Thrd.Join();
mt2.Thrd.Join();
mt3.Thrd.Join();
}
}
MyThread declares the semaphore sem, as shown here:
static Semaphore sem = new Semaphore(2, 2);
This creates a semaphore that can grant up to two permits and that initially has both 
permits available.
C# PDF File & Page Process Library SDK for C#.net, ASP.NET, MVC
functions. Able to create, load, merge, and split PDF document using C#.NET code, without depending on any product from Adobe. Compatible
acrobat combine pdf; add pdf files together
C# PDF Page Insert Library: insert pages into PDF file in C#.net
for each of those page processing functions, such as how to merge PDF document files NET, how to reorganize PDF document pages and how to split PDF document in
asp.net merge pdf files; adding pdf pages together
P
A
R
T
I
I
Chapter 23: Multithreaded Programming, Part One  
769
InMyThread.Run( ), notice that execution cannot continue until a permit is granted by 
the semaphore, sem. If no permits are available, then execution of that thread suspends. 
When a permit does become available, execution resumes and the thread can run. In Main( ),
three MyThread threads are created. However, only the first two get to execute. The third 
must wait until one of the other threads terminates. The output, shown here, verifies this. 
(The actual output you see may vary slightly.)
Thread #1 is waiting for a permit.
Thread #1 acquires a permit.
Thread #1 : A
Thread #2 is waiting for a permit.
Thread #2 acquires a permit.
Thread #2 : A
Thread #3 is waiting for a permit.
Thread #1 : B
Thread #2 : B
Thread #1 : C
Thread #2 : C
Thread #1 releases a permit.
Thread #3 acquires a permit.
Thread #3 : A
Thread #2 releases a permit.
Thread #3 : B
Thread #3 : C
Thread #3 releases a permit.
The semaphore created by the previous example is known only to the process that 
creates it. However, it is possible to create a semaphore that is known systemwide. To do 
so, you must create a named semaphore. To do this, use one of these constructors:
public Semaphore(int initialCount, int maximumCount, string name)
public Semaphore(int initialCount, int maximumCount, string name,
out bool createdNew)
In both forms, the name of the semaphore is passed in name. In the first form, if a semaphore 
by the specified name does not already exist, it is created using the values of initialCount and 
maximumCount. If it does already exist, then the values of initialCount and maximumCount are 
ignored. In the second form, on return, createdNew will be true if the semaphore was created. 
In this case, the values of initialCount and maximumCount will be used to create the 
semaphore. If createdNew is false, then the semaphore already exists and the values of 
initialCount and maximumCount are ignored. (There is also a third form of the Semaphore
constructor that allows you to specify a SemaphoreSecurity object, which controls access.) 
Using a named semaphore enables you to manage interprocess synchronization.
Using Events
C# supports another type of synchronization object: the event. There are two types of 
events: manual reset and auto reset. These are supported by the classes ManualResetEvent
andAutoResetEvent. These classes are derived from the top-level class EventWaitHandle.
These classes are used in situations in which one thread is waiting for some event to occur 
770
Part II: Exploring the C# Library
in another thread. When the event takes place, the second thread signals the first, allowing 
it to resume execution.
The constructors for ManualResetEvent and AutoResetEvent are shown here:
public ManualResetEvent(bool initialState)
public AutoResetEvent(bool initialState)
Here, if initialState is true, the event is initially signaled. If initialState is false, the event is 
initially non-signaled.
Events are easy to use. For a ManualResetEvent, the procedure works like this. A thread 
that is waiting for some event simply calls WaitOne( ) on the event object representing that 
event.WaitOne( ) r
it suspends execution of the calling thread until the event is signaled. After another thread 
performs the event, that thread sets the event object to a signaled state by calling Set( ).
Thus, a call Set( ) can be understood as signaling that an event has occurred. After the event 
object is set to a signaled state, the call to WaitOne( ) will return and the first thread will 
resume execution. The event is returned to a non-signaled state by calling Reset( ).
The difference between AutoResetEvent and ManualResetEventis how the event gets 
reset. For ManualResetEvent, the event remains signaled until a call to Reset( ) is made. 
ForAutoResetEvent, the event automatically changes to a non-signaled state as soon as a 
thread waiting on that event receives the event notification and resumes execution. Thus, 
a call to Reset( ) is not necessary when using AutoResetEvent.
Here is an example that illustrates ManualResetEvent:
// Use a manual event object.
using System;
using System.Threading;
// This thread signals the event passed to its constructor.
class MyThread {
public Thread Thrd;
ManualResetEvent mre;
public MyThread(string name, ManualResetEvent evt) {
Thrd = new Thread(this.Run);
Thrd.Name = name;
mre = evt;
Thrd.Start();
}
// Entry point of thread.
void Run() {
Console.WriteLine("Inside thread " + Thrd.Name);
for(int i=0; i<5; i++) {
Console.WriteLine(Thrd.Name);
Thread.Sleep(500);
}
Console.WriteLine(Thrd.Name + " Done!");
P
A
R
T
I
I
Chapter 23: Multithreaded Programming, Part One  
771
// Signal the event.
mre.Set();
}
}
class ManualEventDemo {
static void Main() {
ManualResetEvent evtObj = new ManualResetEvent(false);
MyThread mt1 = new MyThread("Event Thread 1", evtObj);
Console.WriteLine("Main thread waiting for event.");
// Wait for signaled event.
evtObj.WaitOne();
Console.WriteLine("Main thread received first event.");
// Reset the event.
evtObj.Reset();
mt1 = new MyThread("Event Thread 2", evtObj);
// Wait for signaled event.
evtObj.WaitOne();
Console.WriteLine("Main thread received second event.");
}
}
The output is shown here. (The actual output you see may vary slightly.)
Inside thread Event Thread 1
Event Thread 1
Main thread waiting for event.
Event Thread 1
Event Thread 1
Event Thread 1
Event Thread 1
Event Thread 1 Done!
Main thread received first event.
Inside thread Event Thread 2
Event Thread 2
Event Thread 2
Event Thread 2
Event Thread 2
Event Thread 2
Event Thread 2 Done!
Main thread received second event.
First, notice that MyThread is passed a ManualResetEvent in its constructor. When 
MyThread’sRun( ) method finishes, it calls Set( ) on that event object, which puts the 
772
Part II: Exploring the C# Library
event object into a signaled state. Inside Main( ), a ManualResetEvent called evtObj is 
created with an initially unsignaled state. Then, a MyThread instance is created and passed 
evtObj. Next, the main thread waits on the event object. Because the initial state of evtObj
is not signaled, this causes the main thread to wait until the instance of MyThread calls Set( ),
which puts evtObj into a signaled state. This allows the main thread to run again. Then the 
event is reset and the process is repeated for the second thread. Without the use of the event 
object, all threads would have run simultaneously and their output would have been jumbled. 
To verify this, try commenting out the call to WaitOne( ) inside Main( ).
In the preceding program, if an AutoResetEvent object rather than a ManualResetEvent
object were used, then the call to Reset( ) in Main( ) would not be necessary. The reason is that 
the event is automatically set to a non-signaled state when a thread waiting on the event is 
resumed. To try this, simply change all references to ManualResetEvent to AutoResetEvent
and remove the calls to Reset( ). This version will execute the same as before.
The Interlocked Class
One other class that is related to synchronization is Interlocked. This class offers an 
alternative to the other synchronization features when all you need to do is change the 
value of a shared variable. The methods provided by Interlocked guarantee that their 
operation is performed as a single, uninterruptable operation. Thus, no other 
synchronization is needed. Interlocked provides static methods that add two integers, 
increment an integer, decrement an integer, compare and set an object, exchange objects, 
and obtain a 64-bit value. All of these operations take place without interruption.
The following program demonstrates two Interlocked methods: Increment( ) and 
Decrement( ). Here are the forms of these methods that will be used:
public static int Increment(ref int location)
public static int Decrement(ref int location)
Here, location is the variable to be incremented or decremented.
// Use Interlocked operations.
using System;
using System.Threading;
// A shared resource.
class SharedRes {
public static int Count = 0;
}
// This thread increments SharedRes.Count.
class IncThread {
public Thread Thrd;
public IncThread(string name) {
Thrd = new Thread(this.Run);
Thrd.Name = name;
P
A
R
T
I
I
Chapter 23: Multithreaded Programming, Part One  
773
Thrd.Start();
}
// Entry point of thread.
void Run() {
for(int i=0; i<5; i++) {
Interlocked.Increment(ref SharedRes.Count);
Console.WriteLine(Thrd.Name + " Count is " + SharedRes.Count);
}
}
}
// This thread decrements SharedRes.Count.
class DecThread {
public Thread Thrd;
public DecThread(string name) {
Thrd = new Thread(this.Run);
Thrd.Name = name;
Thrd.Start();
}
// Entry point of thread.
void Run() {
for(int i=0; i<5; i++) {
Interlocked.Decrement(ref SharedRes.Count);
Console.WriteLine(Thrd.Name + " Count is " + SharedRes.Count);
}
}
}
class InterlockedDemo {
static void Main() {
// Construct two threads.
IncThread mt1 = new IncThread("Increment Thread");
DecThread mt2 = new DecThread("Decrement Thread");
mt1.Thrd.Join();
mt2.Thrd.Join();
}
}
Synchronization Classes Added by .NET 4.0
The synchronization classes discussed by the foregoing sections, such as Semaphore and 
AutoResetEvent
going as far back as .NET 1.1. As a result, these classes form the core of .NET’s support for 
Documents you may be interested
Documents you may be interested