Why isn’t there a SendThreadMessage function?


Here's an interesting customer question:

Windows has PostMessage and SendMessage. It also has PostThreadMessage but no SendThreadMessage. Why isn't there a SendThreadMessage function? Am I forced to simulate it with an event?

What would this imaginary SendThreadMessage function do? Recall that SendMessage delivers the message directly to the window procedure; the message pump never sees it. The imaginary SendThreadMessage function would have to deliver the message directly to.... what? There is no "thread window procedure" to deliver it to.

Okay, maybe you still intend to process the thread message in your message pump, but you want the caller of the imaginary SendThreadMessage function to wait until you've finished processing the message. But how does it know when you're finished? It can't wait for DispatchMessage to return, since DispatchMessage can't dispatch thread messages. (Where would it dispatch them to?) The processing of the thread message is completely under the control of the message pump. The window manager gives it a thread message, and as far as the window manager is concerned, that's the end of the story.

You might say that the processing of the thread message is complete when somebody next calls GetMessage or PeekMessage, but there's no guarantee that the next call to a message-retrieval function will come from the message pump. Handling the thread message may result in a call to MessageBox, and as a modal function, it will have its own message loop, which will call GetMessage, resulting in your imaginary SendThreadMessage function deciding that message processing is complete when in fact it's still going on.

What should you do instead? Just create a window and send it a message. The scenarios where you would want to use the PostThreadMessage function are very limited and specialized. Under normal circumstances, you should just send a regular window message.

Comments (42)
  1. Anonymous says:

    This makes me think, you can probably create a deadlock by having thread A not call DispatchMessage() in its message pump and having thread B call SendMessage() on an HWND created by thread A.

    That is…  SendMessage() sends something "directly to a window procedure" which works fine if you send a message to your own thread, but if you do so to another thread’s window it requires synchronization and my guess is it relies on the message pump to get it done.

  2. John Knoeller says:

    Actually, there is a good reason to have a SendThreadMessage function, or rather a SendNotifyThreadMessage function.  because the message queue that cross-thread SendMessage uses is of higher priority than the PostMessage queue.

    Because you can SendNotifyMessage() to other threads’ windows, but only PostMessage() to the thread that owns the windows, its impossible to preserve message order between the messages to the thread and messages to threads’ windows.

    [But where would you put this imaginary “notify thread message”? Are you just treating it as “post to front of queue”? That’s not what SendNotifyMessage does. SendNotifyMessage bypasses the queue. it is not a “PostMessage with high priority.” -Raymond]
  3. RCL says:

    It’s unbelieveable how Win32 API mixes two completely separate things: threads and window events. Why the very thing called “thread message loop” exist, despite the fact that most of threads (at least in games) have nothing to do with UI windows whatsoever? A rhetoric question…

    [Of course they mix – how would you keep them completely separate? How can you expect to run an event without a thread? (Maybe they run in magical fairy land.) If your thread has nothing to do with UI, then don’t give it a message loop. -Raymond]
  4. Dean Harding says:

    RCL: you can’t have a message loop without a thread.

    Just because you can have a thread without a message loop doesn’t mean the two are unrelated.

  5. RCL says:

    Raymond & Dean Harding: I was actually complaining about the fact that every thread has its own message queue. I can’t see the necessity of this, neither can I see how threads and window messages are related. Why not relate threads and file handles or sockets then?

    "Message queues" could have been separate kernel objects not directly related to threads, but rather to windows (HWNDs). Any thread could have peek/get/handle the messages from the queue(s).

    Sure, it’s just pure theory.

  6. Dean Harding says:

    It’s easy to say that, but I think you’d end up with all sorts of issues if you actually tried to do it that way. For example, what if the WM_KEYDOWN event is processed by one thread, and WM_KEYUP by another? It’d be a synchronisation nightmare – far simpler to just limit the UI to a single thread.

    I’m guessing it’s also a historical thing – in 16-bit Windows, there was only one thread anyway.

    Besides, it’s my understanding that the message queue data structures are not actually allocated until it’s actually used. So if you have a thread which does no UI stuff, no queue is created.

  7. RCL says:

    Dean Harding: processing events from a single HWND in two different threads would have made no more sense than, say, opening a file handle and reading it in two different threads at once. If one really needed that, he/she could have used usual means of synchronization provided by kernel.

    About message queue not being created when not used: I’d like Raymond confirm this. This –  http://msdn.microsoft.com/en-us/library/ms644928(VS.85).aspx  says explicitly

    "The system automatically creates a message queue for each thread."

    In my opinion, backward compatibility seems to be the only reason to have such a … khm… weird design.

  8. RC says:

    Ok, I found the part of documentation, where it is said, that message queue is not created until first GDI call.

    Still, that does not excuse the design and does not fully cure its ineffeciences. What if I just want to paint an image in memory using GdiPlus primitive drawing functions?

    Having threads and UI messages linked to each other (and even worse, making a single queue for all the windows that thread could open) should not be considered normal.

  9. Alexander Grigoriev says:

    RC,

    Drawing and message processing are two unrelated things. The message queue is created NOT on the first GDI call (GDI is unrelated to the messages), but on a first of GetMessage, PeekMessage, and a few other calls.

  10. RCL says:

    Alexander,

    what are your sources? Mine is http://msdn.microsoft.com/en-us/library/ms644927(VS.85).aspx

    "To avoid the overhead of creating a message queue for non–GUI threads, all threads are created initially without a message queue. The system creates a thread-specific message queue only when the thread makes its first call to one of the User or Windows Graphics Device Interface (GDI) functions."

    They don’t mention Get/PeekMessage specifically, quite the contrary, they state that any GDI call will get the queue created.

    Your words of course sound reasonable, but let’s not assume that the people who implemented UI message handling that way have enough common sense. Cite your sources, if you please.

  11. John Knoeller says:

    Raymond.  Granted that you have access to the source code and I don’t.  But from my experimentation, it appears that when SendMessage is used to send a message to another thread’s window, it doesn’t bypass the queue so much as use a special high priority queue.  The thread owning the window doesn’t get the ‘sent’ message until it calls GetMessage or PeekMessage.  Then while it’s <b>inside</b> GetMessage, it gets hijacked to handle the sent message.

    If you have multiple threads sending messages to a single thread’s window, how would you handle contention between them if not with a queue?

    [This isn’t a source code thing – the behavior of message queues (and non-queued messages) has been documented since Petzold. Sent messages do not go into the message queue; they go into a different place (I don’t know if it has a name) that is checked by GetMessage and friends. If you don’t have access to Petzold or MSDN, as a last resort you can read my book for a description of how message processing works. -Raymond]
  12. Gabe says:

    I can see how if message queues were created now, they might just be separate objects one could create at will, and associate with every window, timer, power state broadcast, etc. Since I can’t imagine how or why I would write a Windows app where a message queue was services by multiple threads, I don’t see where it would do any good.

    In theory you could have Thread A grab a message from the queue, then have Thread B grab another message while Thread A was processing the first message. But then you would have to do all kinds of locking and Thread B would end up having to wait for Thread A anyway, so why bother?

    By having message queues associated with threads, no locking or waiting is necessary. If you need to have a message processed in the background, use a worker thread for it.

  13. Gabe says:

    John Knoeller: Since each sender has to wait until their message is processed, no thread can have more than a single message pending at a time. This means that each message queue could have a mutex, and everybody that wants to SendMessage the thread can wait on the mutex.

    In this implementation it’s actually the kernel doing the queueing (on the mutex wait), and there’s no guarantee that it’s actually a queue (as opposed to threads just being randomly chosen).

  14. IMil says:

    RCL: The MSDN article says "User or GDI functions".

    As you may learn from MSDN (if not from common sense), GetMessage is a function from user32.dll.

    After all, if Windows behaved as you imagine, it would be quite hard to write a working program.

  15. Newbie says:

    Raymond says: “If your thread has nothing to do with UI, then don’t give it a message loop”.

    If I have a non-UI worker thread and I want to tell it (asynchronously) to do something, what would be a good technique/API to use?

    [You have sooooo many options available. For example, a linked list and a semaphore is a popular technique. -Raymond]
  16. Gabest says:

    PeekMessage will surely create that message loop, I know it from experience. Sometimes the thread may miss a message if it cannot reach the first peek or get function fast enough, therefore I create those threads this way:

    • CreateThread, wait event, post messages

    • PeekMessage (no remove), set event

  17. Alexander Grigoriev says:

    RCL,

    To analyze this and other design choices, consider:

    1. How much synchronization do you want to access your windows
    2. Do you want your messages ordered or not.

    3. And other.

    You don’t like that messages for a given window can only be fetched by the creator thread. You also want a message queue per window, not per thread. Let’s see what consequences you’ll get.

    Suppose, you got a message queue per window. Now, how would you implement GetMessage(). Should it go through a list of windows to find out which window has a message.

    Suppose, you allow multiple threads (thread pool) to handle messages for a group of windows. How would you provide a synchronization? You would need to acquire mutexes/crtical sections every here and there, and in the result, you’d really allow to one thread to proceed at any given time. How would you make sure that a sequence of messages for a given window is only handled by a single thread? And on, and on.

    BE careful what you wish for. You may be opening a big can of worms. You know, even with the current window threading model, if you mix threads associated with different threads in a single window hierarchy, you get deadlock hazard here and there, unless you’re EXTREMELY careful and you know EXACTLY what you’re doing. If you allow free thread-window association, it only becomes worse.

  18. fschwiet says:

    The tight coupling between threads and message queues is a historical artifact.  Its not worth criticizing as its obvious been effective in supporting a lot of software.  If you had the freedom to do it over though (which you don’t) you could do better.

    You don’t see this type of coupling in MSMQ.

    My gripe is the existence of SendMessage().  It forces the wndproc to have to handle re-entrancy.  You don’t see that sort of behavior is MSMQ either.

    There’s probably good reasons for this (ie, people wanted to camp the stack until they get their result, rather than go asynchronous) but it really did muddle the model imo.

  19. Alexander Grigoriev says:

    fschwiet,

    MSMQ is overkill for window messages.

    SendMessage doesn’t give you arbitrary reentrancy. Your WndProc can only be called in certain code points. And yes, its synchronous return simplifies your code design.

  20. RCL says:

    Gabe: are you comfortable with current Windows implementation, where

    a) message queue is not associated with HWND, but a thread, so messages from multiple windows are pumped through single loop

    b) thread can receive messages only from the windows it created and you cannot change window-to-thread mapping (correct me if I’m wrong)?

    But even if you’re fine with this, that does not mean that this implementation is a) logical b) efficient

    IMil: Ok, I understand, that message queue gets created when I call GetMessage(). But is it created when I call any GDIPlus (which may wrap around GDI) function? My understanding of MSDN is that it *is* also created then.

    I don’t have Windows right now to test that, but I’d like to spawn ~1k threads (to get statistically meaningful results) and then make them all call some innocent GdiFunc to see how memory consumption changes.

  21. Alexander Grigoriev says:

    RCL,

    I don’t quite understand what threading model you propose. Can you describe it with more details? We only saw what you don’t like in window-thread affinity model. Which model you would like?

  22. RCL says:

    Alexander,

    I don’t think that serializing/ordering events from multiple windows is a common case. If one really wanted that, he/she would go through the pains you described, but I think it’d be rare. Unless someone has weird dependency problems between his/her windows, but that constitutes bad engineering anyway (AFAIK windows does not guarantee any ordering of messages from multiple windows even now, so it’s not safe to rely on).

    [I dunno, if I click on an object in one window, then click on an object in another window, I want those clicks to be processed in order. You apparently don’t mind if the events are processed out of order. I guess I’m a weirdo. -Raymond]

    Tying such different concepts as threads and window messages makes Win32 API *really ugly*. Look at this side effect: you *HAVE* to differentiate, whether thread creates any windows or not – even if this creation is hidden in some obscure API function:

    http://msdn.microsoft.com/en-us/library/ms687025(VS.85).aspx

    “Use caution when calling the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses a wait function with no time-out interval may cause the system to become deadlocked. Two examples of code that indirectly creates windows are DDE and the CoInitialize function. Therefore, if you have a thread that creates windows, use MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx, rather than WaitForMultipleObjects.”

    heh, the Windows way…

  23. RCL says:

    I “propose” normal threading model, as it is implemented in other OSes (before and after 1985), which do not stem from amateurish graphical “shell” on top of “disk operating system”.

    Threads (and processes of course) should not be tied to GUI. Moreover, window management shouldn’t be inside the kernel at all. Kernel should (and does) offer various mechanisms for inter-process communication (and synchronization), which could be used for implementing UI with messaging model of your choice.

    I’m not elaborating further on this, because it’s all pure theory. Windows is built upon backward compatibility and that’s its “killer feature”. When Windows started to give up some backward compatibility (vide Vista) it immediately lost its attractiveness as a platform (people remain with XP and some even start looking for alternatives).

    Because of this, you (we) are doomed to live with design decisions of some unknown 2nd grade student who worked part-time at Microsoft in early 1980s.

    [I always wonder about people who think that insulting someone is a good way to have a conversation. -Raymond]
  24. David Heffernan says:

    [I dunno, if I click on an object in one window, then click on an object in another window, I want those clicks to be processed in order. You apparently don’t mind if the events are processed out of order. I guess I’m a weirdo. -Raymond]

    Oh how I laughed as the house of cards came crashing down.  Nice one Raymond and please keep up the great work in spite of the occasional rude and abusive clientèle!

  25. RCL says:

    As for language, I beg the pardon for being rude. I’m trying to be rude to technical things, not the people :) and only if I see some objective flaws which I can prove. However, using “2nd grade student” as an insult is what I’m very sorry for.

    [Here’s an idea. Instead of only being rude to technical things, try not being rude at all. Just an idea. -Raymond]
  26. David Heffernan says:

    "I can think of a scenario, where painting to a window may be costly (even without some kind of buffering), so processing of WM_PAINT message will affect responsiveness of an unrelated window."

    Paint to a bitmap in a different thread and then blt it to the window in the UI thread.  That way you keep the UI responsive.  Synchronising between the two threads in this hypothetical example is not difficult due to Win32’s exceedingly rich threading and synchronisation API.

    As a point of information, you say "Moreover, window management shouldn’t be inside the kernel at all."  Well, it isn’t, it’s in userland in DLLs like user32, comctl32, shell32 etc.

  27. RCL says:

    David,

    I realize that such problem has a "real-life" solution like the one you described :)

    However, my point is: by using a different (orthogonal to threading) messaging scheme, you could

    a) have more choice about in which thread and in which order you’re going to process messages

    b) avoid allocation of any UI-related resources when you don’t really need it in thread (and without "User or GDI function called" hackery).

    Current Win32 forces you to:

    1) track whether your thread has ever created any window, directly or indirectly, and use different set of thread synchronization functions if it has (e.g. WaitForMultipleObjects vs MsgWaitForMultipleObjects)

    2) create windows which messages need to be processed in order in a single thread, possibly complicating your app and/or inflicting performance hit

    3) be careful about calling "User or GDI functions" in purely worker threads, because they may allocate additional resources (e.g. message queue) for your thread, which may also affect memory footprint and/or performance (with certain number of threads).

  28. RCL says:

    [I dunno, if I click on an object in one window, then click on an object in another window, I want those clicks to be processed in order. You apparently don’t mind if the events are processed out of order. I guess I’m a weirdo. -Raymond]

    Raymond,

    First of all, is it guaranteed *now*? What if those two windows were created by different threads with different message loops?

    Aside from the fact that there would be probably no less than 100ms delay between your clicks (unless you are really quick :) ), such synchronization can be achieved by other, more “clean” ways than pumping  messages from *all* the windows through a single loop.

    Of course, it’s all pure theory, but threading model could have provided the means to wait for a message on a set of HWNDs (just like select() waits on a set of sockets for incoming data) and this way you could order/serialize messages in any possible way.

    Conceptually, sending and receiving window messages is similar to communication through the network, so you may borrow ready paradigms and solutions from that area.

    Now, how would you solve that problem with *current* Win32 implementation?

    Suppose that you have two windows created by two different threads, and you have two events happening simultaneously (let’s suppose you’re able to click quickly :)) in them. How do you guarantee that those clicks will be processed in order?

    [The problem with the “pass a list of HWNDs” is keeping track of that list of HWNDs. This can get complicated when a window you create in turn creates child windows or hidden worker windows that you don’t know about. I’m wondering whether you’re just designing a system on the fly or whether you are referring to some unnamed working window system. -Raymond]
  29. RCL says:

    [The problem with the “pass a list of HWNDs” is keeping track of that list of HWNDs. This can get complicated when a window you create in turn creates child windows or hidden worker windows that you don’t know about. I’m wondering whether you’re just designing a system on the fly or whether you are referring to some unnamed working window system. -Raymond]

    Once again you pointed to some potential problem I overlooked. However, I still believe that this may be solved without resorting to single queue per thread.

    Solution 1 (obvious, but not convenient for applications and not possible with current API which may create hidden parentless windows):

     manually keep track of all HWNDs created when dispatching messages. Signal by a special message about creation of child HWND.

    Solution 2 (convenient, but somewhat “blurs” my proposition, making analogy with sockets less clear):

     route messages from children windows through parent’s message queue by default. That way we will have a single queue for the whole window hierarchy, but it’s still better than having a single queue rigidly associated with thread.

    Yes, I’m “designing” it on the fly, however, I remember that OS/2 had somewhat similar approach – e.g. http://www.edm2.com/os2api/Win/WinCreateMsgQueue.html

    [I think you will find, upon closer investigation, that OS/2 message queues are per-thread, not per-window. They are, in fact, pretty much identical to Win32 message queues. -Raymond]
  30. Alexander Grigoriev says:

    RCL: "Current Win32 forces you to:" <3 items>

    All of those are non-problems. 1) If you create a non-GUI thread, you don’t care if any non-GUI API created a window. If it did, it’s not well-designed. Better designed API creates its own thread; I’m pretty sure GDI+ does exactly that.

    2) Yyour I code operates on certain set of your data; menu command and window messages can modify that data and change some global state. If you want to do that multithreaded, OK, but the pain that you inflict on yourself by having to syncronize access to the shared state exceeds any hypotetical gain. Typical design implies all GUI state managed by a single thread, and any possible long-running operations performed by worker threads. EVen with that simple scheme many people fail to implement necessar synchronization.

    3) the issue is not resources. You don’t have to care whether you accidentally created a message queue. In fact, if you called a function that creates a message queue implicitly, you most likely want the queue.

    I still fail to see what you’d gain from your proposed changes.

  31. RCL says:

    [I always wonder about people who think that insulting someone is a good way to have a conversation. -Raymond]

    I’m not a native English speaker and I have no idea how do my words *feel*, but neither "2nd grade student" for an early 1980s Microsoft employee nor "amateurish graphic shell" for Windows in 1985 are insults. I think I’m close to truth in former case and fair in the latter.

  32. RCL says:

    David,

    if you laughed, I suppose that you take for granted, that Windows guarantees some kind of ordering *now*. So please tell, whether it is actually possible to have Raymond’s clicks processed in order, if those windows were created by different threads? Let’s see if this is really a “common case”.

    [This topic is covered in my 2005 PDC talk, “Five things every Win32 programmer should know.” -Raymond]
  33. David Heffernan says:

    "Now, how would you solve that problem with *current* Win32 implementation?

    Suppose that you have two windows created by two different threads, and you have two events happening simultaneously (let’s suppose you’re able to click quickly :)) in them. How do you guarantee that those clicks will be processed in order?"

    Why would you want to solve this problem?  That is why would you create UI windows in different threads within the same app?  If you just follow the rules and do all GUI in a single thread then everything is peachy.  Do you actually have a credible scenario in which you need to create UI windows in different threads within the same app?

    It’s a bit bizarre for someone who professes to know nothing about Windows starts a fight with Raymond on the topic of Windows messages!

    And as for your language, as a native English speaker I can assure you that "amateurish graphic shell", "heh, the Windows way… " and "doomed to live with design decisions of some unknown 2nd grade student" are offensive and rude.

    Raymond is spot on, if you framed your questions in a polite and respectful manner the knowledgeable people here would have been more inclined to engage.  That’s just basic human nature.  A good rule of thumb is only ever to write something that you would be prepared to say face to face to a colleague or friend.

  34. David Heffernan says:

    RCL:

    "I suppose that you take for granted, that Windows guarantees some kind of ordering *now*. So please tell, whether it is actually possible to have Raymond’s clicks processed in order, if those windows were created by different threads?"

    No, but the point is that you run the UI out of a single thread and then the ordering is guaranteed.

  35. RCL says:

    > Why would you want to solve this problem?  That is

    > why would you create UI windows in different threads

    > within the same app?  If you just follow the rules

    > and do all GUI in a single thread then everything is

    > peachy.  Do you actually have a credible scenario in

    > which you need to create UI windows in different

    > threads within the same app?

    Let me tell why we’re talking about that problem

    1) I complained about current implementation of threads, where every thread has a messages queue (even in cases where it doesn’t actually want it, e.g. if it only calls GDI functions).

    2) Asked to propose something better I described a possible scheme, where message queues are bound to HWNDs and messages are received more or less the same way as datagrams are received by sockets.

    3) Alexander Grigoriev (and Raymond) told me, that this scheme would introduce synchronization problems and out-of-order message handling. Raymond offered an example, where in order message handling would be preferable.

    4) I proposed using the mechanism similar to select() on the set of sockets to wait for a message on set of HWNDs and thus process them in order.

    5) Fighting back, I asked, how would they implement in order processing with current rigid binding message queues to threads to show, that current implementation *has* synchronization problems, which cannot be addresed as easily as in my imaginary scheme.

    My example is not purely theoretical, although its primary role is to show that flaw already exists. Doing all the GUI in single thread is not a generic solution. I can think of a scenario, where painting to a window may be costly (even without some kind of buffering), so processing of WM_PAINT message will affect responsiveness of an unrelated window.

  36. RCL says:

    Alexander,

    1) Imagine that you are writing a crossplatform application, where you have to abstract system-specific functions like synchronization (yes, I know about pthreads-win32). Now, how do you know if thread that calls that function will ever create windows (in Windows sense)? Do you have to contaminate your API with parameters like bWillCreateWindows passed to synchronization functions?

    2) This is indeed less of a problem. Still, current implementation ties your windows to thread that created them, which I perceive as a limitation.

    3) Won’t such an implicitly created queue cause problems for a thread without message loop? And I have no idea about overhead caused by worker thread having its own message queue, but no matter how small it is, it’s conceptually wrong to assume that threads are somehow related to GUI subsystem. It’s more or less the same as allocating a per-thread buffer for receiving network messages no matter whether this thread will ever create a socket (and later "improving" it by allocating the said buffer after any winsockets function is called)

  37. MadQ says:

    Creating a multi-threaded GUI application in Windows is actually not very difficult. The AttachThreadInput function has been around since Windows 95. One of the first multi-threading demonstrations I saw on Win95 was an MDI application that ran each MDI-child in a separate thread. The document windows just did something similar to the Beziers or Mystify screen savers, but all of the windows remained responsive, and even played nice with each other.

    Also, let’s not forget about AmigaOS (still the only OS with full-blown preemptive multitasking, and able to run useful applications with 512KB of RAM and a single 880K floppy disk.) AmigaOS handles all keyboard/mouse window focusing, etc. in one single dedicated process. GUIs remain responsive even if the application is deadlocked.† How do you like THEM apples?

    † Well, at least that was true until the various Magic* GUI libraries became popular.

    Sigh! I’m waxing nostalgic again. I want my A4000 back. I kinda miss those late night session with all those meditating gurus. I think I’ve been dreaming of blinking red boxes.

  38. Alexander Grigoriev says:

    RCL,

    1) You don’t need to care. If you create worker thread, just use plain WaitForSingleObject/MultipleObjects.

    2) It’s not a limitation. If you think you need to move your window to a different thread, think again about problems it will create.

    3)won’t be a problem.

    Again, with any windowing system you have to understand how it works and what are implications of using it in multiple threads. With your hypothetical system you’ll have more pain without much (if any) gain.

  39. Dean Harding says:

    RCL: I think you’re seriously overestimating the "seriousness" of these "limitations". Windows applications have been written for over 15 years with these "limitations" and you’re the first person I’ve heard of who’s complained about this.

    Of course, this in itself shouldn’t invalidate your claim, but I can’t see a coherent alternative which is actually simpler than the way Windows currently works. You’re making comon things harder in order to simplify things which have little practical value.

  40. Bryan says:

    @RCL:

    If you’re really writing some kind of game then you should take industry experience to heart and avoid the over-use of threads.  In addition to that, your threads shouldn’t care about whether there’s a Window or not unless they created said window.  I can guarantee that in 99% of situations you will destroy performance by trying to have random threads updating your UI.  Your game’s abstract Window Manager should probably handle that if you’re doing something cross-platform.

    Then the only thing you need to do is make the Window Manager thread-safe and compliant with how it might get called by Win32 and you’re good to go.

  41. Kaenneth says:

    How big is an empty Window message queue anyway?

    I recall a figure of around 1mb of memory per thread, which would make thousands of threads a very bad design choice (that might have been .net specific or something…), so what’s the amount added by a queue of zero items? (hmmm, plus broadcast messages I suppose…)

    What happens if the queue isn’t being emptied?, I suppose other threads blocked while awaiting a response (like UIA) would hang, but does an asynchronous message ever timeout? (or are WMs inherently synchronous?)

    I’m currently working on software for Microsoft Surface (using the WPF based sdk)where multiple, simultainous, syncronized inputs are happening, and the application must always be responsive even if 10 different users or fingers of the same user, or even 10 fingers of each of 10 users are interacting with different UI controls. Having all the UI events occur on a single thread is much easier than if they were on different threads, since they interact with each other (such as when using multiple fingers to resize/rotate an object).

    You just have to follow one simple rule, never, ever, EVER block the UI thread. You don’t need a thousand worker threads, I just handle any interesting UI events with as little code as possible to create a workitem, enqueue it, and set the ‘hasWork’ semaphore for the single worker thread. A single queued item may get expanded to mutliple sub-items in the queue, so that the worker dosn’t block as well, and multiple database queries can be pending.

    I suppose what would be the hard part (displaying the results when the queue item has been processed) is taken care of by WPF, I just enqueue a delegate on the Dispatcher for the UI thread, and it’ll run on the correct thread, undating the contents of the element in question. That’s probably done with Window Messages internally.

    I havn’t had to deal with WM_s since Win 3.11, and I don’t miss them one bit. It’s not like I don’t enjoy low-level coding, I still do some assembly, and greatly enjoy reading about the details Raymond describes, but it’s like having a little backyard garden with a few plants compared to having to till 200 acres. The little bit I’ve done myself makes me appreciate what the professionals have done for me.

  42. Alexander Grigoriev says:

    Kaenneth,

    A message queue is limited to 10000 messages by default. And not every thread gets it. BUT prety much every thread gets 1 MB of stack space reserved.

    Asynchronous message will never cause the posting thread to block. This is why it’s called asynchronous.

Comments are closed.