UI thread is blocking a background thread calling a COM object
I am working on an application that communicates with an external device via a third-party COM library. I'm attempting to have all communication to the device go through a background thread both to prevent p开发者_开发知识库roblems with communication from screwing up my app and to get rid of some other complexities introduced by having communication in the UI thread.
The problem is that whenever something happens that causes the main UI thread to block (i.e. MessageBox.Show being called or even just moving the window around the screen), the communication with the device on the background thread stops as well.
Is there any way (short of a totally separate process) to break the two threads far enough apart that they won't interfere with each other? (Note, the exact same code with some math calculations to slow things down a bit works just fine, it's only when I'm using the COM library that I have the issue)
The behavior you observe can be explained if the following two conditions are true.
- The 3rd party COM library is designed to be run in a single threaded apartment
- You are creating an instance of a class from the library on the UI thread
Since the UI thread runs in an STA (single threaded apartment) and the COM class was created on that thread then all calls to the class originating from a thread other than the UI thread will be marshalled onto the UI thread itself. If the UI thread is blocked then all calls to the COM class will block as well.
I would like to fill in on Brian's answer.
Could it be that you are forgetting to call TrySetApartmentState(ApartmentState.STA)
for your worker thread? If so, I believe your worker thread is running in MTA by default and all STA objects get created on a separate STA thread (possibly even main UI thread). You should make sure your worker thread joins a STA and see if that helps.
Other than this, COM objects can be registered as main-STA. IIRC, this is uncommon. Main-STA objects MUST live in the main UI thread. If this happens to be your case, I believe your only option is to resort to worker process instead of a worker thread.
精彩评论