CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Oct 2001
    Location
    lake of fire and brimstone
    Posts
    1,628

    How to use CCriticalSection

    Hi,

    I'm trying to figure out how to use CCriticalSection. I have a worker thread using AfxBeginThread that continuously adds values to a CArray in one of my classes:

    void CMyClass::Function_Called_In_Thread()
    {
    int Value = ...;

    MyArray.Add(Value);
    }

    In the meantime, the user interface visualizes the data on screen (using a timer set every 40 ms) using:

    void CMyClass::Function_For_Screen()
    {
    MyCriticalSection.Lock();

    Show_On_Screen(MyArray[i]);

    MyCriticalSection.Unlock();
    }

    This is how I use the critical section. I've tried also to use critical section additionally here:


    void CMyClass::Function_Called_In_Thread()
    {
    MyCriticalSection.Lock();

    int Value = ...;

    MyArray.Add(Value);

    MyCriticalSection.Unlock();
    }

    In the latter case however, nothing gets showed on screen. If I don't do this however, the program still crashes at times in the function for the screen when trying to access my array at a certain position. What is the correct way to use CCriticalSection such that the data gets displayed on screen correctly and the program doesn't crash?
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: How to use CCriticalSection

    Well, as J.Newcomer wrote in his essay: The Best Synchronization Is No Synchronization!
    Is your worker thread only writes data into array and your main GUI thread only reads this data in, then a better way would be not use any synchronization at all.
    Just define some user message (from the WM_APP range), let the worker thread PostMessage this message and pass the data as PostMessage parameter(s), and let the main thread handle this message, fill data in the array and work with this array.
    Victor Nijegorodov

  3. #3
    Join Date
    Nov 2002
    Location
    California
    Posts
    4,556

    Re: How to use CCriticalSection

    Quote Originally Posted by VictorN View Post
    Is your worker thread only writes data into array and your main GUI thread only reads this data in, then a better way would be not use any synchronization at all.
    Just define some user message (from the WM_APP range), let the worker thread PostMessage this message and pass the data as PostMessage parameter(s), and let the main thread handle this message, fill data in the array and work with this array.
    Just to be clearer, these two paragraphs describe two different architectures. In the first, synchronization is indeed needed if a worker is writing data into an array and the GUI thread is reading it from the same array. The reason synchronization is needed is precisely because access to the same memory is being made by two different threads. Consider a case where the worker is deleting data from the array. Without synchronization, the GUI thread could easily go past the new end of the array, into corrupted memory.

    When Victor says (at the end of the first paragraph) that "a better way would be not use any synchronization at all", he is intorducing a different architecture, which is described in the second paragraph. In this second architecture, the worker thread does not touch the array. The worker thread's sole job is to supply the GUI thread with data for the array, leaving the GUI thread with the responsibility of actually storing the data into the array. This second architecture does not need synchronization for the reason that there is no shared memory, i.e., only the GUI thread ever touches the array.

    In answer to some others of your question, it probably crashes when synchronization is not used for precisely the reasons described above. The array is a templated collection class. When the worker adds data to the array, if there is not sufficient memory already allocated for the array, a typical collection class will re-allocate memory for the array and copy contents to the new allocation. Meanwhile, the GUI thread is still operating on the older values, which are now all meaningless and corrupted memory locations. You thus need synchronization.

    When you add synchronization, you need to tell the GUI thread when to display. Add some sort of signalling. The worker could, for example, PostMessage a custom message to the GUI thread when it is done adding data to the array. The handler in the GUI thread for this custom message could then call "Invalidate()" or some such, so as to cause the GUI thread to re-paint the sceen with the newly added data.

    Mike

  4. #4
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: How to use CCriticalSection

    Good explained, Mike!
    Victor Nijegorodov

  5. #5
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,125

    Re: How to use CCriticalSection

    Since we are getting into details....

    Mike,

    What you say is mainly correct. But there are MANY implementations where it is perfectly valid to update in one thread and read in another WITHOUT synchronization. The key is determining if the object in question presents a consistent view at all points in time

    Consider the simple "Add()" that was in the OP.

    If the code actually adds the new item, and then increments the count; there is no need for synchronization. If thereader thread access the collection after the item is "really" added, but the count has not been incremented, it will function exactly the same as if the call occured before the add.

    On the otherhand, if the exposed "Count" member is incremented FIRST, there is definately a race condition such as you posted.

    An additional concern is typically iterators (many of which are invalidated by a modification to the collection. Hoever there are collection libraries that address this by taking a snapshot of the collection's state.

    Finally the principle of "immutable objects" can eliminate all synchronization requirements, and is a technique rapidly gaining acceptance as the amount of parallization increases. Under this architecture, and "Add" (or any other altering action) would create a NEW collection, rather than modifying the existing one.

    This is the ultimate in RAII (Resource Allocation Is Initialization) and ALL methods (including private and protected - excluding those called solely from the constructor) would be declared as "const".
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

  6. #6
    Join Date
    Oct 2001
    Location
    lake of fire and brimstone
    Posts
    1,628

    Re: How to use CCriticalSection

    Quote Originally Posted by MikeAThon View Post
    When you add synchronization, you need to tell the GUI thread when to display. Add some sort of signalling. The worker could, for example, PostMessage a custom message to the GUI thread when it is done adding data to the array. The handler in the GUI thread for this custom message could then call "Invalidate()" or some such, so as to cause the GUI thread to re-paint the sceen with the newly added data.

    Mike
    Hi Mike,

    Sorry I didn't reply sooner but on the 20th I had to go to Uganda to bury my father in law and I'm only recently back. So if I get it straight I could post a message to the document (CMyClassDoc) class where I start the worker thread from and where the data is stored in an array and the CMyView class where the data is displayed won't risk crashing anymore when I call Invalidate() about every 40ms?
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞
    ۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞۞

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured