limiting simultaniously executing threads

S

siddharthkhare

Hi All,
I have a block of code. I don't want more than five threads to enter
this block simultaneously...

Some thing like this

lock(MyObject)
{
....do work here.
}

so this will allow only one thread to enter at once .

what i want is a effect like

lock(MyObject1) || lock(MyObject2) || lock(MyObject3) ||
lock(MyObject4) || lock(MyObject5)
{
....do work here.
}

This obviously does not compile.


so how can i do this .
1)Do i have to write my own thread pool and limit the number of threads
to 5?
2)Can i do it using using the thread pool class provided in .net ?
3)Can i do it with without using any of the thread Pool class (.net
threadPool or custom thread pool class ) instead use some specific type
of lock to achieve this.

...may be i can maintain some counter and make thread sleep for some
time ..but...I am thinking there might be a better and more clean
solution than this one...

Appreciate any ideas...

Thanks
Sidd
 
L

Lebesgue

What you need to use is Semaphore, which would be the most elegant solution.
Semaphores are not implemented in .NET (I hope someone here will explain
why).
But .NET provides us with WaitHandles - AutoResetEvents and
ManualResetEvents and WaitHandle.WaitAll/Any methods which can help you with
solving this issue.

Definition of semaphore
http://en.wikipedia.org/wiki/Semaphore_(programming)
 
J

Jon Skeet [C# MVP]

Lebesgue said:
What you need to use is Semaphore, which would be the most elegant solution.
Agreed.

Semaphores are not implemented in .NET (I hope someone here will explain
why).

I think it was just an oversight, really.
But .NET provides us with WaitHandles - AutoResetEvents and
ManualResetEvents and WaitHandle.WaitAll/Any methods which can help you with
solving this issue.

Alternatively, it's pretty easy to write a semaphore using
Monitor.Wait/Pulse, which is a more "natively .NET" way of doing
things.

I'm sure there are plenty of semaphore implementations available on the
net - I must include one in MiscUtil some time...
 
L

Lebesgue

Hi Sidd,
Here I provide a sample Semaphore implementation using Win32 API. I hope it
will be helpful to you.
usage:

Semaphore s = new Semaphore(5, true);

s.Wait();
//a maximum of 5 threads will be allowed in this section
s.Signal();

//<code>
using System.Runtime.InteropServices;

namespace System
{
[StructLayout(LayoutKind.Sequential)]
internal struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}

internal enum WaitResult
{
WAIT_ABANDONED = 0x00000080,
WAIT_IO_COMPLETION = 0x000000C0,
WAIT_OBJECT_0 = 0x00000000,
WAIT_TIMEOUT = 0x00000102
}

/// <summary>
/// Summary description for Semaphore.
/// </summary>
public class Semaphore : IDisposable
{
private IntPtr hSemaphore;

[DllImport("kernel32.dll", SetLastError=true)]
private static extern IntPtr CreateSemaphore(ref SECURITY_ATTRIBUTES
securityAttributes, int initialCount, int maximumCount, string name);
[DllImport("kernel32.dll")]
private static extern bool ReleaseSemaphore(IntPtr hSemaphore, int
lReleaseCount, IntPtr lpPreviousCount);
[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32", SetLastError=true, ExactSpelling=true)]
private static extern Int32 WaitForSingleObject(IntPtr handle, Int32
milliseconds);

private static uint INFINITE = 0xFFFFFFFF;

/// <summary>
/// Creates a semaphore initialized in it's nonsignalled state
/// </summary>
/// <param name="maxCount">maximum number of threads</param>
public Semaphore(int maxCount) : this(maxCount, false)
{
}

public Semaphore(int maxCount, bool initiallySignalled) :
this(initiallySignalled ? maxCount : 0, maxCount)
{

}

public Semaphore(int initialCount, int maxCount) : this(initialCount,
maxCount, null)
{

}

protected Semaphore(int initialCount, int maxCount, string name)
{
if (maxCount < 0 || initialCount < 0)
{
throw new ArgumentException("initialCount and maximumCount must not be
negative");
}

if (initialCount > maxCount)
{
throw new ArgumentException("initialCount must not be more than
maximumCount", "initialCount");
}

SECURITY_ATTRIBUTES attr = new SECURITY_ATTRIBUTES();

hSemaphore = CreateSemaphore(ref attr, initialCount, maxCount, name);
if (hSemaphore == IntPtr.Zero)
{
int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
throw new ApplicationException("Semaphore could not be created, error
code: " + error);
}
}

public void Dispose()
{
try
{
CloseHandle(hSemaphore);
}
finally
{
hSemaphore = IntPtr.Zero;
}
}

public void Wait()
{
int o = WaitForSingleObject(hSemaphore, (int)INFINITE);
WaitResult r = (WaitResult)o;
}

public void Signal()
{
if (!ReleaseSemaphore(hSemaphore, 1, IntPtr.Zero))
{
int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
if (error == 0)
{
throw new ApplicationException("Semaphore was already in it's signalled
state");
}
else
{
throw new ApplicationException("Semaphore could not be released, error
code: " + error);
}
}
}
}
}
//</code>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top