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)?
-
possible duplicate of [How to update the GUI from another thread in C#?](http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c) – Servy Apr 23 '14 at 21:09
-
@Servy I don't see how that is a duplicate? – user247702 Apr 23 '14 at 21:10
-
How is that a duplicate? – Denis Apr 23 '14 at 21:10
-
@Stijn I don't see how it's not. It describes exactly how to add a message to the message queue. – Servy Apr 23 '14 at 21:10
-
@Denis You update the UI from a non-UI thread by adding items to the message pump; adding items to the message pump is the means by which you schedule code to run in the UI thread. The message pump is the means by which that task is accomplished. – Servy Apr 23 '14 at 21:11
-
1Guys.. 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. – Eduard Dumitru Apr 23 '14 at 21:11
-
1P/Invoke the `PostMessage` function. Voila.... – Cody Gray - on strike Apr 23 '14 at 21:14
-
@CodyGray Why would you go through all of that work instead of using the tools provided by the framework? – Servy Apr 23 '14 at 21:15
-
@Denis - You have 2 approaches. First one.. Simply execute what you wanted to execute later but asap as part of the event handler you're already in *but* right after a call to Application.DoEvents - see how that goes. Second: Right after the code of your existing event handler issue a message to the message pump like so : this.BeginInvoke( () => { ... your code here ... }); – Eduard Dumitru Apr 23 '14 at 21:16
-
I've written plenty of multi-threaded code in my life, and if we're all right in interpreting the question as involving only a single thread, then I don't understand how Servy's proposed duplicate is a in fact a duplicate. – Cody Gray - on strike Apr 23 '14 at 21:27
-
@CodyGray As I explained in earlier comments, the means by which one marshals to the UI thread from a non-UI thread is to post a message to the message pump. There is nothing preventing one from doing this from the UI thread, other than that there is rarely ever a need to do so. All of the solutions in the proposed duplicate solve this exact problem, they just don't call what they're doing "posting a message to the message pump", they call it "marshaling to the UI thread", despite the fact that they are the exact same thing. Using `PostMessage` is unnecessarily complicating the program. – Servy Apr 24 '14 at 13:55
2 Answers
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 theHandle
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
andlParam
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, includingIntPtr.Zero
if you don't need any custom data.

- 239,200
- 50
- 490
- 574
-
+1 for @CodyGray coming back to SO after a long period of absence. Now I have someone to fight with again :P – Federico Berasategui Apr 23 '14 at 21:44
-
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 Apr 24 '14 at 13:56
-
@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 Feb 12 '15 at 20:20
-
@default.kramer Try it and see if it works, given that you're currently unsure if it will work for you. – Servy Feb 12 '15 at 20:23
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;
} );
}

- 3,242
- 17
- 31