Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Vagarities of Multiple threads in Windows

Vagarities of Multiple threads in Windows

Scheduled Pinned Locked Moved C / C++ / MFC
c++asp-netdata-structureshelpquestion
14 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Lost User

    Bram van Kampen wrote:

    Started to fill in Details, Controls, etc, and the App Clock Ticks are no longer recognised.

    That seems unlikely, unless you are somehow blocking them or throwing them away somewhere. Where do you handle the actual tick messages?

    B Offline
    B Offline
    Bram van Kampen
    wrote on last edited by
    #4

    Well, I also consider it Unlikely, but that is what both Concept mistakes and stupid Bugs are made of. The Tick Messages are sent to the Application. The Application has a List of Structures, consisting of: the hWnd of the Dialog, the Default TimeOut, and the Current Count. Upon every tick the Top Count get decremented, and, when it reaches 0, a Registered Windows Message, WM_REG_TIME_OUT is sent to all Dialogs, in Sequence. The CTimedDialog primitive answers to this by a virtual OnDlgTimeOut(), which by default ends the dialog by OnEndDialog(IDABORT). If the Dialog ends for "Natural" reasons, the EndDialog() of CTimedDialog Pops the reference to the Top Dialog of the list, and resets the Current Count of the new Top Object to it's Default value. I have used a CRITICAL_SECTION where needed, but did not go over the top with belts and braces. The Time-Out bar on the dialogs is more of a debug feature than anything else. It assures me that the clock is ticking, and that things did not deadlock. Thanks for giving me the foothold for assuring me that I am not doing something fundamentally wrong,as other books and autors seem to suggest. (NEVER mix a Worker and a GUI Thread) my Concept is at least not wrong in your judgement. I Start looking for a stupid mistake somewhere. Timed and Activity based actions are notoriously difficult to debug. Stupid Mistakes, (and I made many in the past 60 odd years), are the most difficult ones to find. I'll let you know when I discover what went wrong. I also think that when I get it right, that the subject is of sufficient interest to merit an article. Regards, :)

    Bram van Kampen

    L 1 Reply Last reply
    0
    • B Bram van Kampen

      Well, I also consider it Unlikely, but that is what both Concept mistakes and stupid Bugs are made of. The Tick Messages are sent to the Application. The Application has a List of Structures, consisting of: the hWnd of the Dialog, the Default TimeOut, and the Current Count. Upon every tick the Top Count get decremented, and, when it reaches 0, a Registered Windows Message, WM_REG_TIME_OUT is sent to all Dialogs, in Sequence. The CTimedDialog primitive answers to this by a virtual OnDlgTimeOut(), which by default ends the dialog by OnEndDialog(IDABORT). If the Dialog ends for "Natural" reasons, the EndDialog() of CTimedDialog Pops the reference to the Top Dialog of the list, and resets the Current Count of the new Top Object to it's Default value. I have used a CRITICAL_SECTION where needed, but did not go over the top with belts and braces. The Time-Out bar on the dialogs is more of a debug feature than anything else. It assures me that the clock is ticking, and that things did not deadlock. Thanks for giving me the foothold for assuring me that I am not doing something fundamentally wrong,as other books and autors seem to suggest. (NEVER mix a Worker and a GUI Thread) my Concept is at least not wrong in your judgement. I Start looking for a stupid mistake somewhere. Timed and Activity based actions are notoriously difficult to debug. Stupid Mistakes, (and I made many in the past 60 odd years), are the most difficult ones to find. I'll let you know when I discover what went wrong. I also think that when I get it right, that the subject is of sufficient interest to merit an article. Regards, :)

      Bram van Kampen

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #5

      Sounds fine to me - but then what do I know, I've only been programming for 50 years. BTW, that other message that you received from me appears to have been a mis-post by the hamsters.

      B 2 Replies Last reply
      0
      • L Lost User

        Sounds fine to me - but then what do I know, I've only been programming for 50 years. BTW, that other message that you received from me appears to have been a mis-post by the hamsters.

        B Offline
        B Offline
        Bram van Kampen
        wrote on last edited by
        #6

        Hi Richard, Well I'm only a Novice myself. Cut my teeth on programming in 1974 on a punch card machine. Decided that that could not represent the future, and specialised in pure mathematics instead. Was declared mad by fellow students, Number Theory was taught by elderly professors in the less well funded old departmental buildings. Who on earth could be interested in large prime numbers. No Application at all in any other field. The sexy subjects of the day were differential topology, differential geometry, Functional Analysis, Projective Geometry, Algebra, and other useful subjects for the science of physics. Really got in to programming in the late 1980's with a Commodore64. It started from there. Well, I need to do some serious debugging. You will be first on the list to let you know were and what the bug is. Regards and thanks, :) :)

        Bram van Kampen

        1 Reply Last reply
        0
        • L Lost User

          Sounds fine to me - but then what do I know, I've only been programming for 50 years. BTW, that other message that you received from me appears to have been a mis-post by the hamsters.

          B Offline
          B Offline
          Bram van Kampen
          wrote on last edited by
          #7

          Well Richard, Did not mean to upset you. My native language is Dutch, and, I Don't Do Sarcasm, but Do do Self depreciation. From what you wrote, I concluded that in your valued judgement, my Basic design is possibly right, but that I made a stupid mistake somewhere in the code base. I responded along these lines From your response, I think that you think that I was sarcastic in my reply, I was not, I was genuine and tried to reflect on the fact that I am genuinely aware of my own fallibility, and need to start chasing down a stupid mistake I made, in stead of the whole concept being wobbly. In my experience GDI debugging issues break down into a variety of issues. A first one is, expecting the GDI system to do things that it fundamentally can not. In that case, trying to debug is flogging a dead horse. The best thing there is often to start again, and salvage what you can. Many bugs are what I call 'Stupid' ones. Hard to Find, but, when found, trivial to resolve. an == ipv an =, or viceversa, Missing or misplaced Brackets, calling a wrong but similarly named function, etc. Well I'm sure you've been there, and can add to the list. In short, things that compile right, but act differently than as intended by the author. I was grateful that you condoned the model I had, and by extension suggested that I must have made a 'stupid mistake' somewhere. That is far better news than that 'Your Model is Wrong'. I make 'Stupid mistakes' on a semi regular basis. (I try to avoid the habit for as much as I Can) I think Most Programmers do the same. That's what debugging is for. :) :)

          Bram van Kampen

          L 1 Reply Last reply
          0
          • B Bram van Kampen

            Well Richard, Did not mean to upset you. My native language is Dutch, and, I Don't Do Sarcasm, but Do do Self depreciation. From what you wrote, I concluded that in your valued judgement, my Basic design is possibly right, but that I made a stupid mistake somewhere in the code base. I responded along these lines From your response, I think that you think that I was sarcastic in my reply, I was not, I was genuine and tried to reflect on the fact that I am genuinely aware of my own fallibility, and need to start chasing down a stupid mistake I made, in stead of the whole concept being wobbly. In my experience GDI debugging issues break down into a variety of issues. A first one is, expecting the GDI system to do things that it fundamentally can not. In that case, trying to debug is flogging a dead horse. The best thing there is often to start again, and salvage what you can. Many bugs are what I call 'Stupid' ones. Hard to Find, but, when found, trivial to resolve. an == ipv an =, or viceversa, Missing or misplaced Brackets, calling a wrong but similarly named function, etc. Well I'm sure you've been there, and can add to the list. In short, things that compile right, but act differently than as intended by the author. I was grateful that you condoned the model I had, and by extension suggested that I must have made a 'stupid mistake' somewhere. That is far better news than that 'Your Model is Wrong'. I make 'Stupid mistakes' on a semi regular basis. (I try to avoid the habit for as much as I Can) I think Most Programmers do the same. That's what debugging is for. :) :)

            Bram van Kampen

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #8

            Uh-oh, language problems again. My sincere apologies, you certainly did not upset me, and I am sorry if my reply sounded sarcastic. When I said "what do I know, I've only been programming for 50 years.", I was being, or trying to be, ironic. The point was supposed to be that even after that much time, I still have a lot to learn, and still make stupid mistakes every day. As to your problem, I doubt that you have made a stupid mistake, more likely just one of those infernal bugs that are difficult to track down. Lost coun t of the times ... ;)

            B 1 Reply Last reply
            0
            • L Lost User

              Uh-oh, language problems again. My sincere apologies, you certainly did not upset me, and I am sorry if my reply sounded sarcastic. When I said "what do I know, I've only been programming for 50 years.", I was being, or trying to be, ironic. The point was supposed to be that even after that much time, I still have a lot to learn, and still make stupid mistakes every day. As to your problem, I doubt that you have made a stupid mistake, more likely just one of those infernal bugs that are difficult to track down. Lost coun t of the times ... ;)

              B Offline
              B Offline
              Bram van Kampen
              wrote on last edited by
              #9

              Language Problems again indeed. Sorry for getting the Wrong end of the stick. I call those things 'Stupid'. That reflects my feeling when, after two days stepping trough code into ever deeper levels, I find in the code I wrote a few years ago, deep inside the bowels of working code something like:

              if(abc=PQR){ do this }else{ do something else}

              Worked fine for three years, Changed something, which (Although I long forgot the details of the How and should call the else,(which of course never happens), and the program breaks at run time.) You know the run yourself! Working Code, Go tru the documentation, and even when you look at the offending line, you can still overlook it. It Must be There you say. Let's look at the Assembler Code! Hey, the Whole 'if' and 'else' statement have no Code. At the same time, it worked for years. You Doubt Compiler Settings, did I have a bad #define somewhere that caused this. Then it dawns! '=' in stead of '=='. (Or some error of that kind) Then is my bodily reaction to feel Stupid. First of all for not properly testing years ago, but then again, I'm on my own, and there is often pressure of time. One needs to produce something that works, and Our own shop, the main user of the software is often gagging for it. Secondly, for making the typo in the first place. It was not the fact that I did not know the difference between, in this case '=' and '==', but there are other typo's. Thirdly for not believing that the Compiler compiled correctly. Yes, the beast is near coming of age at 19, but, it is trusty, and I am aware of it's vagarities. The Other option is always that I have a Concept Wrong. Something that worked, in the past, but the strict rules were not followed, and the failure to follow the rules comes home to roost. This can ultimately mean re-starting from the beginning, and flushing existing code. What's new for me is multithreaded programming. I've read quite a few articles on it, and the do's and dont's are so scary and forbidding, one would conclude that multithreading in MFC is all but impossible. At the same time MsOffice95 uses it liberally. The point is, that I'm fledgling to write stuff like that, and when things go wrong is: Was it a Typo, or, did I fall in One of the Pitfalls. Then there is lack of Information. Does the Windows Timer Stuff start a New Thread, (if so, of what kind, GUI or Worker), or is it a kludge in the Message System. At least Peace between us has broken out again. Sorry again that I ever

              L 1 Reply Last reply
              0
              • B Bram van Kampen

                Hi, I am still struggling on in Silence with Multiple threads, and See working Code break for no apparent reason following minor Edits. I have read several articles about it, and, if I take all advice to hart, the answer is "You Can't" The Preferred Method of One Expert leads to grave Demise by another. I am writing a Dialog Based system where a user Logs In, and, perform certain transactions. I am trying to implement a Controlled Log Out (and return to Base) in the absence of User Activity (Mouse Moves, Clicks, Kb Keys Pressed) In Adittion, when TimeOut comes Close, a Small ProgresBar+ Message Appears , counting Down, only XX Seconds remaining. I constructed a New Class, CTimedDialog, and a new App Class, CTimedWinApp. The Latter maintains a list of the m_hWnd of the Dialog Stack, and has a Timer, 1 tick per Second. The 'OnInitDialog' of CTimedDialog (This is a Class that sits between CDialog and the Ultimate UserDialog Class)registers the Class with CTimedWinApp. Upon Time-Out, A Registered Message(WM_TIME_OUT) is '::SentMessage'ed from the timer thread,to the hWnd from the Top of the List, following tru to the bottom, giving each dialog the chance to handle the message, and do a Cleanup (if required), and to close the all dialogs, and, so returning to the Base of the initial menu screen. In adition, as each Dialog 'Knows' it's timeout value, I set up a separate timer in each CTimedDialog, that initially shows a Progress Bar, and a Text Message to display the remaining time. This timer updates the text with SetWindowText(...) and the ProgressControl with SetProgress(...) Yes, the Progress Controls had their ranges set. All worked to perfection when I built a Skeleton Application, of essentially blank Dialogs. Started to fill in Details, Controls, etc, and the App Clock Ticks are no longer recognised. Question, Do I have a hard to chase Bug, or, do I do something Wrong. The Core code involved is quite large, too large to publish here, and covers several files. I can mail the lot to whoever is interested as a ZIP. As a Bottom line, there are multiple ways to skin a cat. MFC is capable of multithreading, witness the existence of MS-Office We need to find the Right way of running Multiple threads in MFC from MS. The guidance for now seems to be: don't Regards, :) :) Regards :)

                Bram van Kampen

                L Offline
                L Offline
                leon de boer
                wrote on last edited by
                #10

                The fact you have been programming for years and the weird behaviour leads me to ask. The usual trap for someone of that experience and first moving into multitasking is not knowing when to use the word "VOLATILE" in front of a variable declaration. So lets ask the obvious do you know when you have to use "VOLATILE" in some instances and why. The corollary to that is are you sure you haven't missed any in your code given your symptoms. In normal single thread work you may only have ever run across the word when directly accessing hardware ports but it is far more critical in multitasking. You get symptoms very similar to what you describe.

                In vino veritas

                B 1 Reply Last reply
                0
                • B Bram van Kampen

                  Language Problems again indeed. Sorry for getting the Wrong end of the stick. I call those things 'Stupid'. That reflects my feeling when, after two days stepping trough code into ever deeper levels, I find in the code I wrote a few years ago, deep inside the bowels of working code something like:

                  if(abc=PQR){ do this }else{ do something else}

                  Worked fine for three years, Changed something, which (Although I long forgot the details of the How and should call the else,(which of course never happens), and the program breaks at run time.) You know the run yourself! Working Code, Go tru the documentation, and even when you look at the offending line, you can still overlook it. It Must be There you say. Let's look at the Assembler Code! Hey, the Whole 'if' and 'else' statement have no Code. At the same time, it worked for years. You Doubt Compiler Settings, did I have a bad #define somewhere that caused this. Then it dawns! '=' in stead of '=='. (Or some error of that kind) Then is my bodily reaction to feel Stupid. First of all for not properly testing years ago, but then again, I'm on my own, and there is often pressure of time. One needs to produce something that works, and Our own shop, the main user of the software is often gagging for it. Secondly, for making the typo in the first place. It was not the fact that I did not know the difference between, in this case '=' and '==', but there are other typo's. Thirdly for not believing that the Compiler compiled correctly. Yes, the beast is near coming of age at 19, but, it is trusty, and I am aware of it's vagarities. The Other option is always that I have a Concept Wrong. Something that worked, in the past, but the strict rules were not followed, and the failure to follow the rules comes home to roost. This can ultimately mean re-starting from the beginning, and flushing existing code. What's new for me is multithreaded programming. I've read quite a few articles on it, and the do's and dont's are so scary and forbidding, one would conclude that multithreading in MFC is all but impossible. At the same time MsOffice95 uses it liberally. The point is, that I'm fledgling to write stuff like that, and when things go wrong is: Was it a Typo, or, did I fall in One of the Pitfalls. Then there is lack of Information. Does the Windows Timer Stuff start a New Thread, (if so, of what kind, GUI or Worker), or is it a kludge in the Message System. At least Peace between us has broken out again. Sorry again that I ever

                  L Offline
                  L Offline
                  Lost User
                  wrote on last edited by
                  #11

                  Yes, been through that more times than I care to remember; but that's all part of the fun. :thumbsup:

                  B 1 Reply Last reply
                  0
                  • L leon de boer

                    The fact you have been programming for years and the weird behaviour leads me to ask. The usual trap for someone of that experience and first moving into multitasking is not knowing when to use the word "VOLATILE" in front of a variable declaration. So lets ask the obvious do you know when you have to use "VOLATILE" in some instances and why. The corollary to that is are you sure you haven't missed any in your code given your symptoms. In normal single thread work you may only have ever run across the word when directly accessing hardware ports but it is far more critical in multitasking. You get symptoms very similar to what you describe.

                    In vino veritas

                    B Offline
                    B Offline
                    Bram van Kampen
                    wrote on last edited by
                    #12

                    Well, I know and use 'volatile' (where appropriate). It is essentially a compiler directive to tread carefully when optimising. It indicates that an agent of which the compiler is not aware can change the value unexpectedly. (which could include other threads). First of all, one can not really rely on this for synchronisation, (One does not know when the monitor thread is interrupted, and the Other thread changes the value.) Furthermore it is quite inefficient as a synchronisation method. It typically means burning CPU Cycles waiting for something to happen. The better way is to put the thread to sleep, by the use of something like WaitForSingleObject(). That means that the CPU Cycles, in stead of being burned, can be used to speed up the printing of that 40 page report in Excell that is churning in the background. By using other synchronisation objects, such as CriticalSections, Mutexes and Semaphores (I prefer the SDK Versions, as the MFC versions are really Crap in MFC42), you can Manage and Control access to sections of code and GLOBAL and STATIC variables Note that the Stack is thread safe, as in Windows, every thread has it's own private stack. Globals and Static Data however is stored on the same heap to which is available to all threads, however, not so easily by hardware threads, but that's a (very long) story for another day Well, I'm 99.9% Sure that the use of 'volatile' is not at issue here, but I will certainly keep your much valued comment in mind Kind Regards :) :) N.B. I Like your Signature

                    Bram van Kampen

                    L 1 Reply Last reply
                    0
                    • L Lost User

                      Yes, been through that more times than I care to remember; but that's all part of the fun. :thumbsup:

                      B Offline
                      B Offline
                      Bram van Kampen
                      wrote on last edited by
                      #13

                      :)

                      Bram van Kampen

                      1 Reply Last reply
                      0
                      • B Bram van Kampen

                        Well, I know and use 'volatile' (where appropriate). It is essentially a compiler directive to tread carefully when optimising. It indicates that an agent of which the compiler is not aware can change the value unexpectedly. (which could include other threads). First of all, one can not really rely on this for synchronisation, (One does not know when the monitor thread is interrupted, and the Other thread changes the value.) Furthermore it is quite inefficient as a synchronisation method. It typically means burning CPU Cycles waiting for something to happen. The better way is to put the thread to sleep, by the use of something like WaitForSingleObject(). That means that the CPU Cycles, in stead of being burned, can be used to speed up the printing of that 40 page report in Excell that is churning in the background. By using other synchronisation objects, such as CriticalSections, Mutexes and Semaphores (I prefer the SDK Versions, as the MFC versions are really Crap in MFC42), you can Manage and Control access to sections of code and GLOBAL and STATIC variables Note that the Stack is thread safe, as in Windows, every thread has it's own private stack. Globals and Static Data however is stored on the same heap to which is available to all threads, however, not so easily by hardware threads, but that's a (very long) story for another day Well, I'm 99.9% Sure that the use of 'volatile' is not at issue here, but I will certainly keep your much valued comment in mind Kind Regards :) :) N.B. I Like your Signature

                        Bram van Kampen

                        L Offline
                        L Offline
                        leon de boer
                        wrote on last edited by
                        #14

                        You said "Furthermore it is quite inefficient as a synchronisation method. It typically means burning CPU Cycles waiting for something to happen. The better way is to put the thread to sleep, by the use of something like WaitForSingleObject()." First the method is not necessarily inefficient (it can be a lot faster than alternatives) and you can not use WaitForSingleObject to solve the problem in any way because the problem is you don't know when the change will occur. WaitForSingleObject hangs around and waits when you know a CHANGE OF SOMETHING MUST OCCUR. That function is of no use for the sort of problem you are dealing with it is used more for asynchronous transfers. The next part is correct. Sychronization is the issue and CriticalSections, Mutexes and Semaphores are the only real way to get around it but THEY CAN BE EXTREMELY INEFFICIENT. A well used volatile with careful coding around the variable can save lots of messing around with synchronization in the simplest situations which is often 90% of cases. It is however NO GUARANTEED FIX you still have to understand what your threads are doing with memory access, the when where and how factors. This statement by you => "All worked to perfection when I built a Skeleton Application, of essentially blank Dialogs. Started to fill in Details, Controls, etc, and the App Clock Ticks are no longer recognised." That tends to suggest you have a synchronization issue because your message posts are going AWL. The app clock tick should be picked up and delivered by DispatchMessage and it can't get lost unless something is going wrong with the memory .... It is delivered to a window based on handle. I would start with following the code for that tick message because it should be dead easy to put a watch on and see where it is getting dispatched to and why it is failing.

                        In vino veritas

                        1 Reply Last reply
                        0
                        Reply
                        • Reply as topic
                        Log in to reply
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes


                        • Login

                        • Don't have an account? Register

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • World
                        • Users
                        • Groups