views:

605

answers:

6

In this thread (posted about a year ago) there is a discussion of problems that can come with running Word in a non-interactive session. The (quite strong) advice given there is not to do so. In one post it is stated "The Office APIs all assume you are running Office in an interactive session on a desktop, with a monitor, keyboard and mouse and, most importantly, a message pump." I'm not sure what that is. (I've been programming in C# for only about a year; my other programming experience has primarily been with ColdFusion.)

A: 

Wikipedia suggests it means the program's main Event Loop.

vincebowdren
+5  A: 

The "message pump" is a core part of any Windows program that is responsible for dispatching windowing messages to the various parts of the application. This is the core of Win32 UI programming. Because of its ubiquity, many applications use the message pump to pass messages between different modules, which is why Office applications will break if they are run without any UI.

Wikipedia has a basic description.

JSBangs
I believe it is impossible to write a windows app without a message loop, thus *all* applications use the message pump.
Hogan
Command-line apps without a message loop run just fine.
JSBangs
You can also write simple GUI apps without one - for example, you can pop up message boxes without your own app having a message loop in your app.
anon
+3  A: 

John is talking about how the windows system (and other window based systems - x-windows, original mac os....) implement asynchronous user interfaces using events via a message system.

Behind the scenes for each application there is a messaging system where each window can send events to other windows or event listeners -- this is implemented by adding a message to the message queue. There is a main loop which always runs looking at this message queue and then dispatching the messages (or events) to the listeners.

Here is a wikipedia article that shows example code of a basic windows program -- and as you can see at the most basic level a windows program is just the "message pump". http://en.wikipedia.org/wiki/Message_loop_in_Microsoft_Windows.

So, to pull it all together. The reason a windows program designed to support a UI can't act as a service is because it needs the message loop running all the time to enable UI support, if you implement it as a service as described it won't be able to process the internal asynchronous event handling.

Hogan
A: 

I think that this Channel 9 discussion has a nice succinct explanation:

This process of window communication is made possible by the so-called Windows Message Pump. Think of the Message Pump as an entity that enables cooperation between application windows and the desktop.

Richard Ev
wow... that is a horrible and misleading quote. (An "entity"? Err.. no.)
Hogan
entity - object: something that exists as or is perceived as a single separate objecthttp://encarta.msn.com/dictionary_1861608661/entity.html
Matthew Whited
+13  A: 

A message loop is a small piece of code that exists in any native Windows program. It roughly looks like this:

MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{ 
   TranslateMessage(&msg); 
   DispatchMessage(&msg); 
} 

The GetMessage() Win32 API retrieves a message from Windows. Your program typically spends 99.99% of its time there, waiting for Windows to tell it something interesting happened. TranslateMessage() is a helper function that translates keyboard messages. DispatchMessage() ensures that the window procedure is called with the message.

Every GUI enabled .NET program has a message loop, it is started by Application.Run().

The relevance of a message loop to Office is related to COM. Office programs are COM-enabled programs, that's how the Microsoft.Office.Interop classes work. COM takes care of threading on behalf of a COM coclass, it ensures that calls made on a COM interface are always made from the correct thread. Most COM classes have a registry key in the registry that declares their ThreadingModel, by far the most common ones (including Office) use "Apartment". Which means that the only safe way to call an interface method is by making the call from the same thread that created the class object. Or to put it another way: by far most COM classes are not thread-safe.

Every COM enabled thread belongs to a COM apartment. There are two kinds, Single Threaded Apartments (STA) and a Multi Thread Apartment (MTA). An apartment threaded COM class must be created on an STA thread. You can see this back in .NET programs, the entry point of the UI thread of a Windows Forms or WPF program has the [STAThread] attribute. The apartment model for other threads is set by the Thread.SetApartmentState() method.

Large parts of Windows plumbing won't work correctly if the UI thread is not STA. Notably Drag+Drop, the clipboard, Windows dialogs like OpenFileDialog. And any ActiveX control and most COM servers, like Office.

A hard requirement for an STA thread is that it should never block and must pump a message loop. The message loop is important because that's what COM uses to marshal an interface method call from one thread to another. Although .NET makes marshaling calls easy (Control.BeginInvoke or Dispatcher.BeginInvoke for example), it is actually a very tricky thing to do. The thread that executes the call must be in a well-known state. You can't just arbitrarily interrupt a thread and force it to make a method call, that would cause horrible re-entrancy problems. A thread should be "idle", not busy executing any code that is mutating the state of the program.

Perhaps you can see where that leads: yes, when a program is executing the message loop, it is idle. The actual marshaling takes place through a hidden window that COM creates, it uses PostMessage to have the window procedure of that window execute code. On the STA thread. The message loop ensures that this code runs.

Hans Passant
A: 

Thanks! I think you've just explained something I've been puzzling about.

My program runs through a large number of RTF files to extract two pieces of information used to construct a medical report number. Rather than try and figure out how the formatting instructions in RTF work, I decided to just open them in Word and pull the text out from there (without actually starting the GUI). Occasionally, the program hiccuped in the middle of processing one file, and left a Word thread open attached to that document (I still have to figure out how to shut that one down). When I re-ran the program, of course I got a notification that there was a thread using that file, and did I want to open a read-only copy? When I said Yes, the Word GUI suddenly popped up from nowhere and started processing the files. I was wondering why that happened; but it looks like maybe once the dialog box popped up the message pump started pushing the main GUI to Windows as well?

And now I'm puzzling about something else. Yesterday I posed this question as an unregistered user - and then cleared my cookies so that it couldn't figure out who I was; now as a registered user I have to start over from scratch :-/ Why don't they make it easier to connect cookie-based registration with OpenID-based? Hmf.

Matt Gutting