CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 2 of 3 FirstFirst 123 LastLast
Results 16 to 30 of 31
  1. #16
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,241

    Re: MFC: PostMessage and Handling it without the hassle (and a question).

    Quote Originally Posted by VladimirF View Post
    This, unfortunately, will fail if you manage to post two or more messages before your window proc will get to process them.
    Probably there are also other problems as long as we are trying to break the oldest but goodest "classic" way.
    Still digging and having fun...
    Last edited by ovidiucucu; March 17th, 2015 at 02:15 PM.
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  2. #17
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: MFC: PostMessage and Handling it without the hassle (and a question).

    Quote Originally Posted by VladimirF View Post
    This, unfortunately, will fail if you manage to post two or more messages before your window proc will get to process them.
    Correct, and the reason why this wouldn't have been possible in the particular case I needed this for.

    the solution I posted in #1 doesn't have that issue, and applying the change codeplug suggested in #2 works as well and makes it even better. AND you can capture.
    You do need to be careful about what you capture of course, since the message is posted, the processing of the lambda is asynchronous to where it's been declared, so the captured variables might already be gone by the time you get to execute the lambda body.


    I also have a thing against any class member variables that only serve to make a class member function behave 'differently'.

  3. #18
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,241

    Re: MFC: PostMessage and Handling it without the hassle (and a question).

    Quote Originally Posted by OReubens View Post
    You do need to be careful about what you capture of course, since the message is posted, the processing of the lambda is asynchronous to where it's been declared, so the captured variables might already be gone by the time you get to execute the lambda body.
    That's the reason why I made the capture by value. NO need to be a rocket scientist in order to know what happens with local variables when go out of scope.

    Quote Originally Posted by VladimirF View Post
    This, unfortunately, will fail if you manage to post two or more messages before your window proc will get to process them.
    Please detail!
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  4. #19
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,241

    Re: MFC: PostMessage and Handling it without the hassle (and a question).

    Quote Originally Posted by OReubens View Post
    I also have a thing against any class member variables that only serve to make a class member function behave 'differently'.
    Absolutely agree.
    However, the actual parameters can only (sic ) serve to make a class member function behave 'differently', as well.
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  5. #20
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: MFC: PostMessage and Handling it without the hassle (and a question).

    Quote Originally Posted by ovidiucucu View Post
    Please detail!
    Code:
    void CMyDialog::OnFunButtonClicked()
    {
         PostedFunction( [](){ AfxMessageBox("Fun"); }
         PostedFunction( [](){ AfxMessageBox("More fun"); }
    }
    with your suggestion, you'll have more fun twice and never have some normal fun.

  6. #21
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,241

    Re: MFC: PostMessage and Handling it without the hassle (and a question).

    Quote Originally Posted by OReubens View Post
    Code:
    void CMyDialog::OnFunButtonClicked()
    {
         PostedFunction( [](){ AfxMessageBox("Fun"); }
         PostedFunction( [](){ AfxMessageBox("More fun"); }
    }
    with your suggestion, you'll have more fun twice and never have some normal fun.
    Right, and I knew that. Although it's hard to believe that somebody can have the idea to write something like that (I discovered it just doing tests to find a solution), let's think like an "good architect" which believes that all developers are idiots.
    And have more fun finding a KISS solution without writing wrappers everywhere, like all "good architects" do every time something is not exactly like they think to be.

    [ later edit ]
    Just joking and having fun. No intention to offend the good architects...
    Last edited by ovidiucucu; March 19th, 2015 at 05:37 AM.
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  7. #22
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: MFC: PostMessage and Handling it without the hassle (and a question).

    The post was obviously the "smallest possible case where it fails" because we don't want all the irrelevant stuff in our forum posts when poiting out something.

    In this particular case, I did have such cases where multiple posts were being done from a single message handler (though not right one after the other, they're all conditional, but multiple conditions cound be true).

    so more something like
    Code:
    ...
    if (rgbColor==defcolor::yellow)
       PostedFunction( []() { YellowificateEverything(); } );
    ...
    if (vehicle==car)
       PostedFunction( []() { Vroom(); } );
    ...
    if ( GetNumPassengers()>1 ) 
       PostedFunction( []() { OptimizePassengerSeatingArrangements(); } );

    Now, it is possible the user was trying to make a yellow car with multiple passengers, so all 3 posts would be needed

    P.S. The above code is an entirely ficticious example.

  8. #23
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,241

    Re: MFC: PostMessage and Handling it without the hassle (and a question).

    Quote Originally Posted by OReubens View Post
    [...]
    so more something like
    Code:
    ...
    if (rgbColor==defcolor::yellow)
       PostedFunction( []() { YellowificateEverything(); } );
    ...
    if (vehicle==car)
       PostedFunction( []() { Vroom(); } );
    ...
    if ( GetNumPassengers()>1 ) 
       PostedFunction( []() { OptimizePassengerSeatingArrangements(); } );

    Now, it is possible the user was trying to make a yellow car with multiple passengers, so all 3 posts would be needed

    P.S. The above code is an entirely ficticious example.
    Sure.
    But if someone is a good developer and not only a good architect (), has no sweat to put an '=' sign in lambda capture list, instead of shooting a burst in the message queue, from a single message handler.
    Code:
        // ...
        // ...
        // ...
        theApp.PostLambda([=]() // capture all by value
        {
            if (rgbColor == defcolor::yellow)
                YellowificateEverything();
            if (vehicle == car)
                Vroom();
            if (GetNumPassengers() > 1)
                OptimizePassengerSeatingArrangements();
        });
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  9. #24
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,241

    Re: MFC: PostMessage and Handling it without the hassle (and a question).

    To make possible multiple asynchronous lambda calls in the same message handler, one solution is to store them in a list.
    These having been said, my example from post #14 can be improved a little bit as follows:
    Code:
    #include <functional>
    #include <list>
    // ...
    
    class CSomeApplication : public CWinApp
    {
        static const UINT WM_APP_POST_LABDA = WM_APP + 1;
        std::list<std::function<void()> > m_listLambdas;
        // ...
    
    public:
        void PostLambda(std::function<void()> fn);
        // ...
    
        DECLARE_MESSAGE_MAP()
    protected:
        afx_msg void OnAppPostLambda(WPARAM wParam, LPARAM lParam);
        // ...
    };
    Code:
        // ...
        ON_THREAD_MESSAGE(WM_APP_POST_LABDA, &CSomeApplication::OnAppPostLambda)
    END_MESSAGE_MAP()
    
    void CSomeApplication::OnAppPostLambda(WPARAM wParam, LPARAM lParam)
    {
        while (!m_listLambdas.empty())
        {
            if (m_listLambdas.front())     // if is callable,
            {
                m_listLambdas.front()();   // invoke,
            }
            m_listLambdas.pop_front(); // then remove it from list.
        }
    }
    
    void CSomeApplication::PostLambda(std::function<void()> fn)
    {
        m_listLambdas.push_back(fn);        // push lambda into the list
        PostThreadMessage(WM_APP_POST_LABDA, 0, 0);
    }
    Code:
    BOOL CSomeDialog::OnInitDialog()
    {
        CDialog::OnInitDialog();
        // ...
    
        theApp.PostLambda([=]() // capture all by value
        {
            // stuff...
        });
    
        theApp.PostLambda([=]() // capture all by value
        {
            // more stuff...
        });
    
        theApp.PostLambda([=]() // capture all by value
        {
            // much more stuff...
        });
    
        // and so on...
    
        return TRUE;
    }
    For sure, still there are other solutions.
    Digging is fun!
    Last edited by ovidiucucu; March 19th, 2015 at 11:45 AM.
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  10. #25
    Join Date
    Oct 2008
    Posts
    1,456

    Re: MFC: PostMessage and Handling it without the hassle (and a question).

    note that neither this nor your previous example are thread safe, if PostLambda is invoked by different threads. BTW, what's wrong with the unique_ptr<> approach ? if your aim is to avoid the free store allocation, note that std::function will allocate its storage on the heap anyway ( unless the lambda is very small, like a mere this pointer for example ).

  11. #26
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,241

    Re: MFC: PostMessage and Handling it without the hassle (and a question).

    Indeed, the solution from previous example is not thread safe.
    So, to prevent calling CSomeApplication::PostLambda from a thread, other than main application's thread, we can simply use an ASSERT.
    Code:
    void CSomeApplication::PostLambda::PostLambda(std::function<void()> fn)
    {
        ASSERT(::GetCurrentThreadId() == m_nThreadID); // don't call me from other thread, dude!
        m_listLambdas.push_back(fn);                  // add lambda to the list
        PostThreadMessage(WM_APP_POST_LABDA, 0, 0);
    }
    or, if really want to call it from multiple threads, it's no sweat to synchronize the list operations.
    Code:
    class CSomeApplication : public CWinApp
    {
        CCriticalSection m_cs;
        // ...
    Code:
    void CSomeApplication::OnAppPostLambda(WPARAM wParam, LPARAM lParam)
    {
        m_cs.Lock();
        while (!m_listLambdas.empty())
        {
            if (m_listLambdas.front())     // if it's callable,
            {
                m_listLambdas.front()();   // invoke,
                
            }
            m_listLambdas.pop_front(); // and finally, remove it from list.
        }
        m_cs.Unlock();
    }
    
    void CSomeApplication::PostLambda(std::function<void()> fn)
    {
        m_cs.Lock();
        m_listLambdas.push_back(fn);        // add lambda to the list
        m_cs.Unlock();
    
        PostThreadMessage(WM_APP_POST_LABDA, 0, 0);
    }
    Personally, I would like to use the first solution.

    About storing the functions in the list.
    There is an old issue, still present, about MFC macro ON_THREAD_MESSAGE: https://support.microsoft.com/en-us/kb/142415.
    Using the list gets rid of this problem.
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  12. #27
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: MFC: PostMessage and Handling it without the hassle (and a question).

    Quote Originally Posted by ovidiucucu View Post
    Sure.
    But if someone is a good developer and not only a good architect (), has no sweat to put an '=' sign in lambda capture list, instead of shooting a burst in the message queue, from a single message handler.
    Code:
        // ...
        // ...
        // ...
        theApp.PostLambda([=]() // capture all by value
        {
            if (rgbColor == defcolor::yellow)
                YellowificateEverything();
            if (vehicle == car)
                Vroom();
            if (GetNumPassengers() > 1)
                OptimizePassengerSeatingArrangements();
        });
    AGain, too elaborate to give the full explanation, but this wouldn't have worked in this case, they did needed to be independantly posted messages. Besides now you're assuming the handler has easy access to all those things that in this approach need to be captured. The above could be a much heavier approach because you're capturing a lot more.

  13. #28
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: MFC: PostMessage and Handling it without the hassle (and a question).

    Quote Originally Posted by ovidiucucu View Post
    To make possible multiple asynchronous lambda calls in the same message handler, one solution is to store them in a list.
    true but.
    1) you're still having member variables in the class that serve no other purpose than to make a called (posted) function behave differently.
    2) This is a much more elaborate and less elegant solution than just posting the (new-ed lambda).
    3) you might now have to deal with synchronisation if the list needs to be accessible from multiple threads.

  14. #29
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: MFC: PostMessage and Handling it without the hassle (and a question).

    Quote Originally Posted by ovidiucucu View Post
    Code:
    void CSomeApplication::OnAppPostLambda(WPARAM wParam, LPARAM lParam)
    {
        m_cs.Lock();
        while (!m_listLambdas.empty())
        {
            if (m_listLambdas.front())     // if it's callable,
            {
                m_listLambdas.front()();   // invoke,
                
            }
            m_listLambdas.pop_front(); // and finally, remove it from list.
        }
        m_cs.Unlock();
    }
    Well, you would really want to NOT put the invoke of the lamba inside the CS lock.
    For one it might cause a deadlock (and it certainly will if the lambda again posts more lambdas) but even without that case, there might be issues.
    You're also locking a CS for much longer than you really need to, so even if this DOES work, you're blocking your other threads for longer than necessary which lowers throughput, which is one of the reasons to go multithreaded in the first place.

    I said it before on CG, the basics of MT is easy. But it's hard to do right ;-)


    Personally, I would like to use the first solution.
    ;-)

    hence why it thought it was an interesting approach that I wanted to share with you all...
    If you can use it, then by all means do so. If you don't see the point of this, nobody is forcing you to use it

  15. #30
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,241

    Re: MFC: PostMessage and Handling it without the hassle (and a question).

    Another reason why I said "I would like to use the first solution" is to avoid shuffling lambda calls in worker threads. I'm not sure if that matters but who knows... anytime a mighty architect may appear, finding a reason to complain.

    Anyway, still I think "it's better to follow the classic MFC way". Or better said, more headache-less.
    The rest is just the fun of digging...
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

Page 2 of 3 FirstFirst 123 LastLast

Tags for this Thread

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