I was seeing a lot of crashes once I started analyzing search results, and fetching pages. I discovered that the crashes all seemed to happen when multiple threads were all accessing the same document. I was passing a pointer to the IHTMLDocument3 object to the XMLHttpRequest worker threads, and after a little thought, it made sense that this object wasn’t thread-safe, and so I’d need to synchronize my access to it somehow.
This part really puzzled me. I couldn’t figure out a good way to call back my BHO on the main thread, because the BHO doesn’t control the message loop for the main thread, that’s all in IE. And since IE could be using the same object, and I don’t control that code, I couldn’t implement my own manual locking.
Luckily, I came across a life-saving post from Tony Schreiner. He explains that COM objects in IE are not thread-safe by default, but that you can get a wrapped version that adds thread-safe locking by calling CoMarshalInterface(). This gives you a version of the object that you can use on a different thread, without worrying about crashes caused by other threads accessing it at the same time.
It was only a few lines of code, and implementing it removed all the bugs I was hitting. Thanks Tony!