4

I'm building a VSTO add-in: I need to run a background thread, but this thread needs to access COM components (I've implemented IMessageFilter to make this messaging as safe as possible). All threads which access OLE or COM have to be STA I believe; thus, BackgroundWorker is off the table.

I am happy to use the normal thread and set the ApartmentState to STA, but I also need to know when this thread as finished so I can update some UI stuff. I do not want to Join() because it will lock the UI (which is the whole reason I'm using threads!).

Is the best practice to trigger some kind of event at the end of my threaded method, and have the event do the onfinished stuff I need?

OR

Is it better to poll

   while(!_threadFinishedStarting)
   {
        Application.DoEvents();
        Thread.Sleep(100);
   }

As mentioned here: C#.net - How to alert program that the thread is finished (event driven)?

Thanks so much

Community
  • 1
  • 1
user1713993
  • 113
  • 2
  • 7

1 Answers1

3

You can call Thread.SetApartmentState() to select an STA before you start the thread. You must also pump a message loop, a requirement for STA threads. That tends to be difficult and is often skipped, you know you need one if your code deadlocks or your IMessageFilter complains.

Beware of the other requirement, an STA is only efficient when you also create the object you want to use on that same thread. That tends to be a problem in a VSTO add-in, you normally want to use an object provided by the Office object model. You don't get to choose where that object was created.

If that's accurate at all then you are not ahead with creating your own STA thread since the calls get marshaled anyway. In which case a BGW is just fine since you can't get ahead anyway, the call gets marshaled in both cases. There is no free lunch for thread-safety.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Thanks so much Hans. Regarding passing objects, I am wrapping all of my COM calls with VSTOContrib (as Office's COM is so buggy that it seems to need 3rd party disposal). Thus, all my objects are theoretically created in the threads (I am not sure if this completely applies to COM proxied objects though). Heavily controlled STA threads seem to have partially solved the problem for me (BGW couldn't work because it's all MTA which OLE/COM hates). – user1713993 Jul 28 '13 at 22:31
  • 1
    Office programmers forever dig themselves a giant hole they can't get out of when they think that '3rd party disposal' is important. Backgrounder [is here](http://stackoverflow.com/questions/17130382/understanding-garbage-collection-in-net/17131389#17131389). It would be nice when Microsoft could completely paper over the interop, that however doesn't really work. You do have to know a wee bit more about how the gears inside the machine work. Knowing that there are gears isn't exactly the same as knowing how many teeth they have. – Hans Passant Jul 28 '13 at 22:39
  • @HansPassant Are you saying that `GC.Collect()` is the only thing needed to remove references to COM objects in a VSTO solution? That nobody needs `Marshal.ReleaseComObject()`? – Chris May 18 '17 at 20:07