1

I have a main class in Wpf so it's in a MTA and I have to deal with a COM object that needs to be in a STA.

SO I have the following code to create an instance of an object.

COMObject localCOMObject;

Thread thread = new Thread(() =>
{
   try { localCOMObject = new COMObject(); }
   finally { DidFinish= 1; }
});

thread.SetApartmentState(ApartmentState.STA);
thread.Start();

And I also have a list object that have a reference to this object(WorkingObjects)

List<WorkingObject> WorkingObjects= new List<WorkingObject>();
WorkingObject.Add(new WorkingObject(localCOMObject));
...

Further in my code I run

await Task.Run(() => 
{
  Parallel.ForEach(WorkingObjects, WorkingObject=>
  {
      WorkingObject.Execute();
  });
});

And within my Execute method I use my COMObject object and this is when I get the exception:

COM object that has been separated from its underlying RCW can not be used.

It use to work when My code was:

await Task.Run(() => 
{
  COMObject localCOMObject = new COMObject();
  Parallel.ForEach(WorkingObjects, WorkingObject=>
  {
      WorkingObject=localCOMObject ;
      WorkingObject.Execute();
  });
});

But now I need to do things with this outside of my task.

user3704628
  • 143
  • 1
  • 12
  • 4
    A COM object has affinity to the thread on which it got created. So when the thread exits, the COM object is dead as a doornail. There are more bad assumptions, WPF code does not run in the MTA. And an STA thread must always pump a message loop. And Parallel.ForEach() does not accomplish anything on an object that is not thread-safe and whose calls are serialized. Hard to help you. Sample code for a happy STA thread [is here](http://stackoverflow.com/a/21684059/17034). – Hans Passant Feb 13 '17 at 23:25
  • My main thread still exist when I call my Parallel.ForEach plus localCOMObject is initialized in a different thread and still works in my main thread when I use it. – user3704628 Feb 13 '17 at 23:38

1 Answers1

1

I have a main class in Wpf so it's in a MTA (...)

Are you sure? Windows Forms and WPF are specifically meant to run in an STA.

(...) and I have to deal with a COM object that needs to be in a STA.

A COM object cannot outlive its apartment. An STA cannot outlive its thread.

You're creating an STA thread, then you're creating a COM object, and finally this thread exits. If that object is registered to live in an STA, then your object is now in an undefined state and is totally unreliable.

It use to work when My code was:

await Task.Run(() => 

(...)

That's because the object is created either in the MTA apartment (the thread-pool threads use the MTA), or it was created in an STA that is alive while the object is used.

If the object is registered with ThreadingModel set to Both or Free, then it's in the MTA. If the object is set to Single, then it's getting created in a host STA which was not destroyed before you used the object.

acelent
  • 7,965
  • 21
  • 39