Click here to Skip to main content
11,435,451 members (52,741 online)
Click here to Skip to main content

Using Win32 Semaphores in C#

, 30 Sep 2002
Rate this:
Please Sign up or sign in to vote.
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.

[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. Smile | :) (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

Share

About the Author

Robin Galloway-Lunn
Architect
United Kingdom United Kingdom
No Biography provided

Comments and Discussions

 
GeneralYou r da man! Pin
tataobr24-Oct-07 12:18
membertataobr24-Oct-07 12:18 
GeneralSystem.Threading.Mutex Pin
Sau F Lee11-Jul-05 19:13
memberSau F Lee11-Jul-05 19:13 
GeneralC++ DLL Pin
Ed Hopkins18-Aug-04 8:07
memberEd Hopkins18-Aug-04 8:07 
I am responsible for writing a DLL which I am developing in VC++ for various reasons, but one of our our customers uses C# and we've had some minor issues with getting it working. Mostly it works now, but I am curious as to if you know the answers to a few other questions that I've run into while developing this.

Essentially I am thinking of using the WaitForSingleObject Win32 API kernal function to wait for an event that will be getting fired off from the C++ DLL. Does it work the same way that it does in VC++? Are there any wierdnesses to C# that I should be aware of?

I've already run into one strange problem in that it appears that the DLL is not actually loaded (and thus the objects instantiated) until the first function call to the DLL is called from C#. So I had to create a dummy function LoadDLL that just does nothing but forces the DLL to be loaded into memory. Seems sort of hacky, the MSDN suggests using DLLImport to access DLL's but I am accustomed to having an explicit link or else using LoadLibrary.

I don't know if you are still checking this article's posts regularly but in case you do I had a few other more detailed questions.

Thanks.

Ed
GeneraldoEvent() method Pin
eafares2658-Nov-03 10:32
membereafares2658-Nov-03 10:32 
GeneralRe: doEvent() method Pin
Robin Galloway-Lunn8-Nov-03 12:06
memberRobin Galloway-Lunn8-Nov-03 12:06 
GeneralThanks! Pin
Alvaro Mendez11-Aug-03 10:36
memberAlvaro Mendez11-Aug-03 10:36 
GeneralRe: Thanks! Pin
Robin Galloway-Lunn12-Aug-03 1:52
memberRobin Galloway-Lunn12-Aug-03 1:52 
GeneralRe: Thanks! Pin
Robin Galloway-Lunn12-Aug-03 2:05
memberRobin Galloway-Lunn12-Aug-03 2:05 
GeneralProblem Pin
Jhon8-Oct-02 7:46
memberJhon8-Oct-02 7:46 
GeneralRe: Problem Pin
Robin Galloway-Lunn8-Oct-02 23:34
memberRobin Galloway-Lunn8-Oct-02 23:34 
GeneralRe: Problem Pin
Jhon9-Oct-02 11:05
memberJhon9-Oct-02 11:05 
GeneralThreadpool Pin
Marc Clifton1-Oct-02 12:25
memberMarc Clifton1-Oct-02 12:25 
GeneralRe: Threadpool Pin
Robin Galloway-Lunn1-Oct-02 23:58
memberRobin Galloway-Lunn1-Oct-02 23:58 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150428.2 | Last Updated 1 Oct 2002
Article Copyright 2002 by Robin Galloway-Lunn
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid