Click here to Skip to main content
15,867,686 members
Articles / Programming Languages / C#
Article

Using Win32 Semaphores in C#

Rate me:
Please Sign up or sign in to vote.
4.45/5 (9 votes)
30 Sep 20023 min read 124.4K   2.7K   43   13
How to use Windows semaphores in C# to share access to a system resource between many processes.

Screenshot

Introduction

Some applications need to share access to a restricted resource in a coordinated manner on one PC, like a dodgy print driver to which only one application can print at a time. All preemptively multitasking operating systems like Windows and Unix provide a mechanism called semaphores with which several running applications can coordinate access to restricted resources. In my case, I want to make sure that only one application at a time is trying to print a document to my dodgy print driver.

Explanation

Semaphores are named objects in the operating system. If several applications ask the operating system for a semaphore with the same name, then each application will be given a link to the same semaphore in the operating system. Name your semaphores something which you find meaningful and that all application sharing the resource must know. In my code sample I have named the semaphore "sem_DotNetExample" but you should name your semaphore after the resource it is being used to coordinate access to, like "sem_DodgyPrintDriver". Each semaphore keeps a count of how many applications can concurrently use the resource. In my case, I only want one application to use the resource at a time and other applications requesting to use the resource should wait until the resource becomes available. When the semaphore is created the operating system is told how high the count for the semaphore is and each time an application uses the semaphore, the count is decremented. If the count is zero when an application tries to use the semaphore, the application goes into an efficient waiting state, consuming very little CPU time until another application releases the resource. When your application has finished using the resource, it releases the semaphore, incrementing the availability count of the semaphore. Finally when your program shuts down it should clean up and delete its reference to the semaphore.

The Windows operating system provides many functions for working with semaphores, all of which are in the kernel32 library. The source code provides maps to these kernel functions and then makes the calls to the operating system when the application's buttons are clicked by a user. The way to map these functions in the kernel to C# methods is as follows. A working encapsulation of the semaphore functionality is included in the Semaphore class available in the source code download should you wish to include this functionality in your own projects.

C#
[DllImport("kernel32", EntryPoint="CreateSemaphore",
           SetLastError=true,CharSet=CharSet.Unicode)]
private static extern uint NT_CreateSemaphore(
    SecurityAttributes auth,
    int initialCount,
    int maximumCount,
    string name);

[DllImport("kernel32",EntryPoint="WaitForSingleObject",
           SetLastError=true,CharSet=CharSet.Unicode)]
private static extern uint NT_WaitForSingleObject(
    uint hHandle,
    uint dwMilliseconds);

[DllImport("kernel32",EntryPoint="ReleaseSemaphore",
           SetLastError=true,CharSet=CharSet.Unicode)]
[return : MarshalAs( UnmanagedType.VariantBool )]
private static extern bool NT_ReleaseSemaphore(
    uint hHandle,
    int lReleaseCount,
    out int lpPreviousCount);

[DllImport("kernel32",EntryPoint="CloseHandle",
           SetLastError=true,CharSet=CharSet.Unicode)]
[return : MarshalAs( UnmanagedType.VariantBool )]
private static extern bool NT_CloseHandle(uint hHandle);

[DllImport("kernel32",EntryPoint="GetLastError",SetLastError=true)]
private static extern uint NT_GetLastError();

To see the application in action, download the demo project and run several instances of the application, say four. Click the "Create" button in each instance of the application to get a handle, or reference, to the semaphore. In each application then click the "Take" button to instruct each application that it should request access to the resource. Only the first application in which you clicked the "Take" button returns immediately with the message "Took the semaphore successfully." and the other instances all go into a waiting state. Now click the "Give" button in the application which owns the semaphore and the next application in the queue will immediately return from its waiting state with the message "Took the semaphore successfully." and so on in turn clicking the "Give" button in each application until each application has had ownership of the semaphore. When you're done, tell the operating system that you're done with the semaphore by closing the handle to it, click the "Destroy" button.

Conclusion

Share your resources well. :-) (This article is dedicated to His Holiness, the 17th Gyalwa Karmapa, Trinley Thaye Dorje)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralYou r da man! Pin
tataobr24-Oct-07 11:18
tataobr24-Oct-07 11:18 
GeneralSystem.Threading.Mutex Pin
Sau Fan Lee11-Jul-05 18:13
Sau Fan Lee11-Jul-05 18:13 
GeneralC++ DLL Pin
Ed Hopkins18-Aug-04 7:07
Ed Hopkins18-Aug-04 7:07 
GeneraldoEvent() method Pin
eafares2658-Nov-03 9:32
eafares2658-Nov-03 9:32 
GeneralRe: doEvent() method Pin
Robin Galloway-Lunn8-Nov-03 11:06
Robin Galloway-Lunn8-Nov-03 11:06 
GeneralThanks! Pin
Alvaro Mendez11-Aug-03 9:36
Alvaro Mendez11-Aug-03 9:36 
GeneralRe: Thanks! Pin
Robin Galloway-Lunn12-Aug-03 0:52
Robin Galloway-Lunn12-Aug-03 0:52 
GeneralRe: Thanks! Pin
Robin Galloway-Lunn12-Aug-03 1:05
Robin Galloway-Lunn12-Aug-03 1:05 
GeneralProblem Pin
Víctor Sánchez8-Oct-02 6:46
Víctor Sánchez8-Oct-02 6:46 
GeneralRe: Problem Pin
Robin Galloway-Lunn8-Oct-02 22:34
Robin Galloway-Lunn8-Oct-02 22:34 
GeneralRe: Problem Pin
Víctor Sánchez9-Oct-02 10:05
Víctor Sánchez9-Oct-02 10:05 
GeneralThreadpool Pin
Marc Clifton1-Oct-02 11:25
mvaMarc Clifton1-Oct-02 11:25 
GeneralRe: Threadpool Pin
Robin Galloway-Lunn1-Oct-02 22:58
Robin Galloway-Lunn1-Oct-02 22:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.