Why do I need to define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA?
Okay, I didn't actually check in the code the checks for this define, but I work next to the guy that did, so the osmotic property of random VSD knowledge guarantees that I can answer this question. First off, this compile error isn't really intended as an error, because you might not have done anything wrong ("It's not you, it's me. I... I'm... just not a multithreaded kind of control."). Think of it as a warning with teeth, a warning that you might actually pay attention to, and a warning that you might end up on this blog trying to figure out. So, why do we have this build break if you can just #define something and make the error go away? Because we want to ensure that you attempt to think about the issue, and . There are a couple of MSDN articles that mention this build break and unfortunately just tell you to define the symbol to make the error go away (I need to track down the writers for those articles and get updates published).
Windows CE (the underlying OS on which Windows Mobile Pocket PC and Smartphone devices, among others, are built) has multiple different COM implementations (this page http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceappservices5/html/wce50oricomdcomapplicationdevelopment.asp covers all of them, I'm just going to pretend that there are two). The "standard" implementation, by virtue of the fact that it's in Windows Mobile devices, is something that I'll refer to as normal COM, and it only supports free threaded*, in-process objects. The "luxury" COM implementation will be referred to as DCOM (rumour has it that the CE team refers to it as "Da Bomb!" internally. I just made that up), and it adds two key features not found in normal COM: network call support, and (most importantly) thread and parameter marshalling. Basically, what this means is that if you have a COM object running on a DCOM device, your parameters will be marshalled for you across threads, and many common synchronization issues simply drop away, as the runtime takes care of them for you. If you have a COM object running on a normal COM device, then you have to ensure that you marshall your parameters correctly for cross-thread calls, and that you handle synchronization yourself. This is VERY VERY important for you to think about, especially if you are porting code from a desktop project to a device project. Think about the future of devices, and the current multicore CPUs on the desktop, and don't assume that your host app will always be single threaded on a single CPU. Many ActiveX controls make assumptions about the environment that they are running in, and normal COM simply doesn't guarantee that those assumptions are true for anything other than single-threaded apps. We've (VSD) seen numerous bugs where apps just hang for no apparent reason, and it almost always comes down to cross-threading issues.
Key takeaway: you need to review all code for cross thread correctness (a.k.a. synchronization), and ensure that calls are made on the proper threads. Then define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA. While you're at it, define _YES_THE_DEFINE_IS_INCREDIBLY_LONG_BUT_I_CAN_ACCEPT_THAT, and don't complain about how long the define is.
*Yes, you can load a control marked as "Apartment" or "Single" threaded on a PPC/SP 2003 (CE4.2) device, but only if the PE header marks the binary as linked for CE 3.0 (PPC 2000/2002, SP 2002). Don't do this, it is a hack, and it probably doesn't work in WM5.0. Anything marked as anything other than "Free" should fail to load on if it was linked for CE 4.2.