0

In a VSTO addin I am starting a new background STA thread ("Thread B") that creates some COM objects, e.g. a PowerPoint.Shape. Now I would like to be able to access this PowerPoint.Shape in my main VSTO STA thread ("Thread A") but I get a "COM object that has been separated from its underlying RCW cannot be used" exception.

I searched online and found (see comment by Kevin Smyth here: COM object that has been separated from its underlying RCW cannot be used) that this can occur because Thread B is no longer alive when I try to access the object in Thread A.

I know that ideally I should not use a background thread at all here but I still would like to know if it is even possible to pass the COM object created on Thread B to Thread A and access it there even though thread B is no longer running.

'We are on the main thread (Thread A)
Dim output As List(Of PowerPoint.Shape) = DoWorkOnThreadB(oSlide)

'Now when I e.g. try to look at some properties of a shape in the list I get the RCW exception.

Private Shared Function DoWorkOnThreadB(oSlide as PowerPoint.Slide) as List(Of PowerPoint.Shape)

    Dim listOfShapes = New List(Of PowerPoint.Shape)()    

    For each oShape as PowerPoint.Shape in oSlide.Shapes
        listOfShapes.Add(oShape)
    Next

    Return listOfShapes

End Function

I also tried to use a ManualResetEvent to wait in Thread B to keep it alive until I am finished with using the object in Thread A but this did not work.

chriscode
  • 121
  • 1
  • 8
  • Do you call ReleaseComObject or FinalReleaseComObject on your object somewhere? – Simon Mourier Sep 09 '21 at 14:35
  • No I never call these methods because I saw the posts by Hans Passant on Stackoverflow that it is better to leave this up to the GC. – chriscode Sep 09 '21 at 19:24
  • 1
    None of the Office objects are thread-safe. COM ensures that all method calls and property accesses are done on the thread that created the object. When that thread terminates then it can of course no longer access any of these members and the logical and inevitable happens: the object dies. You have to keep it running, actively spinning in its dispatcher loop or blocking on an event with MsgWaitForMultipleObject(). [Example](https://stackoverflow.com/a/21684059/17034). – Hans Passant Sep 10 '21 at 18:13
  • @HansPassant thanks for the explanation. I tried using a ManualResetEvent to keep the thread alive but I ended up blocking the Main Thread. I probably implemented it wrong and will try the code in your linked example. – chriscode Sep 10 '21 at 19:23

1 Answers1

0

Try to create these objects on the main thread, and populate their properties on the secondary thread.

Dmitry Streblechenko
  • 62,942
  • 4
  • 53
  • 78