Link to home
Start Free TrialLog in
Avatar of FSOFT-SA
FSOFT-SAFlag for Viet Nam

asked on

Using InitializeCriticalSection on C#

Dear Experts,

I'm porting application from C++ to C#.
In C++, it used InitializeCriticalSection (Win API) in controlling threads.
It also used the structure
typedef struct _RTL_CRITICAL_SECTION { 
    PRTL_CRITICAL_SECTION_DEBUG DebugInfo;   

    // 
    //  The following three fields control entering and exiting the critical 
    //  section for the resource 
    // 

    LONG LockCount; 
    LONG RecursionCount; 
    HANDLE OwningThread;        // from the thread's ClientId->UniqueThread 
    HANDLE LockSemaphore; 
    ULONG_PTR SpinCount;        // force size on 64-bit systems when packed 
} RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;

Open in new window

How can I porting this to C#.
Are there any substitution in C#

Please help.
Regards.
Avatar of chaau
chaau
Flag of Australia image

I think the closest alternative will be to use a "lock" keyword that will mark a section of code a critical section. If you could show us more code (old C++ and new C# code with the comments where you got stuck) we will be able to help you how to isolate a variable for safe multi-thread access. Sorry, I cannot provide any links due to strict "blind link" policy of this site
you may use Mutex class below System.Threading in c# and (one of the) Wait functions and Release function to have an equivalent to EnterCriticalSection and LeaveCriticalSection

see sample code at http://msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx#vcwlkthreadingtutorialexample4mutex

Sara
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Critical Sections and Mutexes are two completely different concepts
??
a critical section is called a 'fast mutex'. why should it be a different concept?

if you enter a cs with success it is the same as calling WaitOne on a mutex and other threads (in case of a named mutex even processes) which also are calling any of the Wait functions have to wait until the mutex is released. so the release would be the same as leaving a cs.

// This example shows how a Mutex is used to synchronize access
// to a protected resource. Unlike Monitor, Mutex can be used with
// WaitHandle.WaitAll and WaitAny, and can be passed across
// AppDomain boundaries.

using System;
using System.Threading;

class Test
{
    // Create a new Mutex. The creating thread does not own the
    // Mutex.
    private static Mutex mut = new Mutex();
    private const int numIterations = 1;
    private const int numThreads = 3;

    static void Main()
    {
        // Create the threads that will use the protected resource.
        for(int i = 0; i < numThreads; i++)
        {
            Thread myThread = new Thread(new ThreadStart(MyThreadProc));
            myThread.Name = String.Format("Thread{0}", i + 1);
            myThread.Start();
        }

        // The main thread exits, but the application continues to
        // run until all foreground threads have exited.
    }

    private static void MyThreadProc()
    {
        for(int i = 0; i < numIterations; i++)
        {
            UseResource();
        }
    }

    // This method represents a resource that must be synchronized
    // so that only one thread at a time can enter.
    private static void UseResource()
    {
        // Wait until it is safe to enter.
        mut.WaitOne();

        Console.WriteLine("{0} has entered the protected area", 
            Thread.CurrentThread.Name);

        // Place code to access non-reentrant resources here.

        // Simulate some work.
        Thread.Sleep(500);

        Console.WriteLine("{0} is leaving the protected area\r\n", 
            Thread.CurrentThread.Name);

        // Release the Mutex.
        mut.ReleaseMutex();
    }
}

Open in new window


of course a mutex is a more expensive resource and therefore it is a good idea to use the lock instead if the advantages of the mutex are not needed.

but the code for using a lock for a real synchronization is not so much "slimmer" as the following code shows:

 
// using System.Threading; 

    class Account
    {
        private Object thisLock = new Object();
        int balance;

        Random r = new Random();

        public Account(int initial)
        {
            balance = initial;
        }

        int Withdraw(int amount)
        {

            // This condition never is true unless the lock statement 
            // is commented out. 
            if (balance < 0)
            {
                throw new Exception("Negative Balance");
            }

            // Comment out the next line to see the effect of leaving out  
            // the lock keyword. 
            lock (thisLock)
            {
                if (balance >= amount)
                {
                    Console.WriteLine("Balance before Withdrawal :  " + balance);
                    Console.WriteLine("Amount to Withdraw        : -" + amount);
                    balance = balance - amount;
                    Console.WriteLine("Balance after Withdrawal  :  " + balance);
                    return amount;
                }
                else
                {
                    return 0; // transaction rejected
                }
            }
        }

        public void DoTransactions()
        {
            for (int i = 0; i < 100; i++)
            {
                Withdraw(r.Next(1, 100));
            }
        }
    }

    class Test
    {
        static void Main()
        {
            Thread[] threads = new Thread[10];
            Account acc = new Account(1000);
            for (int i = 0; i < 10; i++)
            {
                Thread t = new Thread(new ThreadStart(acc.DoTransactions));
                threads[i] = t;
            }
            for (int i = 0; i < 10; i++)
            {
                threads[i].Start();
            }
        }
    }

Open in new window


shortly said, for an exclusive protection of a code block you can do the same with both and a lock is more efficient. but if you have need for smart wait functions like WaitAll or WaitAny or want to pass the handle beyond app domain boundaries, the Mutex is your only choice.

Sara
IMO, a mix of terminology is being used here. Monitors, semaphores, locks, and mutexes (and I think a couple of others) are all tools used to synchronize threads. A "critical section" is just a block of logic that is intended to be atomic in that only one thread can be in that section at a time. The aforementioned tools can be used to ensure this atomic-ness, but each has a different usage/intention.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Threading is not my forte, but I do know that the lock keywork is syntactic sugar for a Monitor. Hopefully that still means the same thing as your "critical section"   = )
a Monitor is a little bit more than a critical section (cs) in winapi. while cs only has initialize, enter, leave, try-enter, delete and spincount-enter (some speed optimization for multi-core) functions, a monitor additionally has pulse functionality (notify waiting threads if released) and wait with timeout. those functions help from dead-lock better than a cs and could avoid bottlenecks by smarter code.

Sara
>>??
>>a critical section is called a 'fast mutex'. why should it be a different concept?

You can't  use a CRITICAL_SECTION over process boundaries. That's the difference, as well as the amount of OS resources they take up therefore.
mutex and critical section are different in scope and the first is mightier and more expensive regarding resources but you said
 
Critical Sections and Mutexes are two completely different concepts
what is wrong as shown.

your assertion is untenable. I am sorry.

Sara
Shown? How exactly? Prove by claim? *shrug*

You show me how to use a critical section over provess boundaries and we'll commence.
our mutual "claim" should be to be sincere.

in my comment, ID:39872814, I posted two code samples which both make a block of logic exclusive for the first thread entering the block. one uses a lock and one uses a Mutex. as we all agree the lock is the c# way to implement a  critical section, the code sample 2 is a proof that a Mutex could be used as well. hence both a cs and a mutex can be used to implement the same "concept" and therefore your assertion that the concepts are totally difficult is a falsity which I successfully disproved. the assertion is also technically wrong as you can see in mfc header afxmt.h where we have classes CSemaphore, CMutex, CEvent, CCriticalSection which all are derived from class CSyncObject.  that means that mfc implements all the "wait objects" by using one baseclass, what should make clear that the concepts are not "totally different" ?

I never said that there are no differences or that a critical section could be used over process boundaries. the task here is to synchronize with threads and to port a critical section, and not to synchronize with another process, so your demands on me seem to be somewhat confused.

by the way, I once implemented a two-phase commit between processes where both server and client used a critical section + shared memory for synchronization of their own parts. so for p2p communication critical sections very well could be used within their limitations.

Sara
There never has been any doubt that both can be used for the same purpose. It is also possible to glue a anchor bolt to a wall. Let's simply call that a 'Schmidt-Breiner Moment".  And yes, we aren't complete idiots.
you seem not to have much knowledge of the synchronization objects. that doesn't excuse your attacks but possible explains them.

I never named anyone here an 'idiot' and protest against your imputation.

Sara