1

Using VB.NET/C# - .Net Framework 3.5. I am currently in a handler for a WinForms event (for example). In the handler I would like to put my own event for the windows message pump but at the end of its queue (assuming it pumps messages FIFO). I would like my handler and any additional handlers for the current event to execute and later on pick up my custom event that I inserted into the queue and call its handler. Any sample code on how I can insert an event into the windows event queue (don't care what language)?

11
  • possible duplicate of How to update the GUI from another thread in C#? Commented Apr 23, 2014 at 21:09
  • @Servy I don't see how that is a duplicate? Commented Apr 23, 2014 at 21:10
  • How is that a duplicate? Commented Apr 23, 2014 at 21:10
  • 1
    Guys.. Denis is only asking how could he defer execution for a particular piece of code. He already is on the GUI thread. He just wants to return to the message pump but still execute something else asap. Commented Apr 23, 2014 at 21:11
  • 1
    P/Invoke the PostMessage function. Voila.... Commented Apr 23, 2014 at 21:14

2 Answers 2

3

If you want to add a message to the queue, then you just need to P/Invoke the PostMessage function. As the documentation says, this function:

Places (posts) a message in the message queue associated with the thread that created the specified window and returns without waiting for the thread to process the message.

Sample P/Invoke declaration:

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
  • hWnd is a handle to your window, the one whose window procedure should receive the message. In WinForms, this can be retrieved using the Handle property.

  • msg is the message you want to post. Of course, you'll need to figure out which one to use here. If one of the standard messages works for your purposes, then you can use that. Otherwise, just define a user-defined message. User-defined messages have a range of values >= WM_USER. So:

    const uint WM_USER = 0x0400;
    const uint UWM_MYGREATMESSAGE = WM_USER + 1;
    const uint UWM_MYOTHERMESSAGE = WM_USER + 2;
    
  • Obviously, wParam and lParam contain message-specific information. If you're using one of the standard messages, their documentation will tell you what to specify here. If you're using a user-defined message, then you can pretty much pass whatever you want here, including IntPtr.Zero if you don't need any custom data.

Sign up to request clarification or add additional context in comments.

4 Comments

+1 for @CodyGray coming back to SO after a long period of absence. Now I have someone to fight with again :P
This is unnecessarily complicating the program. There are already multiple tools built into the framework for posting messages to the message queue, there is no need to complicate the program, reduce maintainability, or increase the opportunities for errors by explicitly using unmanaged code here.
@Servy I know this is an old-ish question, but this answer was useful to me. If you know a way to achieve deferred UI thread execution without PostMessage, could you please create an answer? Note that Control.Invoke is not sufficient (it runs synchronously)... perhaps BeginInvoke would work but it's not obviously correct to me.
@default.kramer Try it and see if it works, given that you're currently unsure if it will work for you.
2

I really enjoyed the engineering example @CodyGray has given. It's been a while since I was doing Win32 stuff in Delphi :).

Still I couldn't keep my fingers afk and had to share this idea I have about what Denis might need because I think it may be a little simpler.

Say you have a block of code. Let's call it A. Let's say that it is composed of 10 statements. Let's call them a0 thru a9. So our block of code looks something like this:

{
    a0;
    a1;
    ...
    a4;
    a5;
    ...
    a8;
    a9;
}

Now say you end up writing this block as the event handler for a Windows Forms control:

void button1_Click(object sender, EventArgs e) {
    a0;
    a1;
    ...
    a8;
    a9;
}

Suddenly you realise that you want to execute a0 thru a4 immediately and defer the execution of a5 thru a9 to a later time. Later meaning as soon as possible but after the message pump became idle.

All you need to do is:

void button1_Click(object sender, EventArgs e) {
    a0;
    a1;
    a2;
    a3;
    a4;

    this.BeginInvoke( () => {
        a5;
        a6;
        a7;
        a8;
        a9;
    } );
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.