Solved

Using InitializeCriticalSection on C#

Posted on 2014-02-18
16
1,123 Views
Last Modified: 2014-03-03
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.
0
Comment
Question by:FSOFT-SA
  • 7
  • 4
  • 2
  • +2
16 Comments
 
LVL 24

Expert Comment

by:chaau
ID: 39869493
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
0
 
LVL 7

Expert Comment

by:Kishan Zunjare
ID: 39869497
0
 
LVL 32

Expert Comment

by:sarabande
ID: 39870056
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
0
 
LVL 86

Accepted Solution

by:
jkr earned 300 total points
ID: 39872287
Critical Sections and Mutexes are two completely different concepts. C# has a 'lock()' keyword that does the same that a CS does while avoiding the overhead of a mutex. Te gist is to

Object lockobj = new Object();

lock (lockobj)
{
// Do your locked work
}

Open in new window


See also http://www.discretevector.com/2008/02/locks-threads-and-this-huh-most-people.html ("Locks, threads and this (huh?)")

In short: You either want a mutex or a CS. Substituting one for the other is not a good idea.
0
 
LVL 32

Expert Comment

by:sarabande
ID: 39872814
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
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 39874033
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.
0
 
LVL 32

Assisted Solution

by:sarabande
sarabande earned 200 total points
ID: 39876190
a mix of terminology is being used here
the terms 'critical section' and 'mutex' were not used (here) for the logical concepts but  for the winapi resource objects of the same names. as the original post was about porting InitializeCriticalSection function from c++ to c#, the 'critical section' referenced is not only a 'block of logic' for exclusive access but also a shared instance of RTL_CRITICAL_SECTION structure which can be used in c/c++ to implement the concept by functions InitializeCriticalSection, EnterCriticalSection, LeaveCriticalSection, DeleteCriticalSection, more ...

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


jkr found out that lock function is the equivalent implementation method in c#.

Sara
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 39877058
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"   = )
0
 
LVL 32

Expert Comment

by:sarabande
ID: 39881975
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
0
 
LVL 86

Expert Comment

by:jkr
ID: 39890853
>>??
>>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.
0
 
LVL 32

Expert Comment

by:sarabande
ID: 39891206
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
0
 
LVL 86

Expert Comment

by:jkr
ID: 39893749
Shown? How exactly? Prove by claim? *shrug*

You show me how to use a critical section over provess boundaries and we'll commence.
0
 
LVL 32

Expert Comment

by:sarabande
ID: 39894361
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
0
 
LVL 86

Expert Comment

by:jkr
ID: 39899493
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.
0
 
LVL 32

Expert Comment

by:sarabande
ID: 39899904
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
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now