COM object that has been separated from its underlying RCW cannot be used exception within threads

Hi,

We are having code in which we start a new thread and set it as STA. This new thread initializes IHTMLWindow2 object and then starts another thread. But, in that second thread if we try to access the IHTMLWindow2 which is initialized in the first thread we are getting this exception "COM object that has been separated from its underlying RCW cannot be used". If we do not set the first thread to STA, we coudn't access the windows in that thread itself, so it needs to be in STA. So how can we access the window initialized in the first thread Please give any suggestions.

I am giving the code here.

Class1.java:

import com.ms.wfc.html.*;

import com.ms.wfc.core.*;

import com.ms.wfc.ui.*;

import com.ms.wfc.html.om.*;

public class Class1 extends DhDocument

{

DhText createdText;

DhText boundText;

public IHTMLWindow2 bottomwin;

public IHTMLWindow2 leftwin;

Helper helperobj;

public Class1()

{

// Required for Visual J++ Form Designer support

initForm();

// TODO: Add any constructor code after initForm call

}

/**

* Class1 overrides dispose so it can clean up the

* component list.

*/

public void dispose()

{

super.dispose();

}

private void initForm()

{

createdText = new DhText();

createdText.setText("Created Text");

boundText = new DhText();

boundText.setID("bindText");

boundText.setBackColor(Color.LIGHTGRAY);

/**

* setBoundElements() will take a list of elements that already are present

* in the HTML document, and binds them to the DhElement list.

*/

setBoundElements(new DhElement[] {boundText});

/**

* setNewElements() takes a list of DhElements and adds them to the HTML document.

*/

setNewElements(new DhElement[] {createdText});

}

protected void onDocumentLoad(Object sender, Event e)

{

bottomwin=this.getWindowPeer().getParent().getParent();

// MessageBox.show("href::"+ bottomwin.getLocation().getHref());

// MessageBox.show("length::"+bottomwin.getLength());

ThreadOne obj1=new ThreadOne(this);

Thread thr1=new Thread(obj1);

thr1.setApartmentState(System.Threading.ApartmentState.STA);

thr1.start();

}

//initDcontroller is called from ThreadOne

public void initDController()

{

leftwin=this.getWindowPeer().getParent();

helperobj=new Helper(leftwin,this);

helperobj.helperfun();

ThreadTwo obj2=new ThreadTwo(helperobj,this);

Thread thr2=new Thread(obj2);

thr2.setApartmentState(System.Threading.ApartmentState.STA);

thr2.start();

}

}

ThreadOne.java:

public class ThreadOne implements Runnable

{

public Class1 clsobj;

public ThreadOne(Class1 obj)

{

clsobj=obj;

}

public synchronized void run()

{

try

{

clsobj.initDController();

}

catch(Exception ex)

{

MessageBox.show("exception in thread1::"+ex.toString());

}

}

}

ThreadTwo.java:

public class ThreadTwo implements Runnable

{

public Class1 clsobj;

public Helper helperobj;

public ThreadTwo(Helper hobj,Class1 obj)

{

helperobj=hobj;

clsobj=obj;

}

public synchronized void run()

{

try

{

//this line tries to access the bottomwin which is initialized by main thread

//it works fine without exception

MessageBox.show("bottomwin length in thread2::"+clsobj.bottomwin.getLength());

//next two lines access the leftwin which is initialized by thr1

//and thr1 is also set to STA

//these lines give the exception COM object that has been separated from its underlying RCW cannot be used

helperobj.helperfun();

//String href=clsobj.leftwin.getLocation().getHref();

}

catch(Exception ex)

{

MessageBox.show("exception in thread2::"+ex.toString());

}

}

}

Helper.java:

public class Helper

{

public Class1 clsobj;

public IHTMLWindow2 leftwin;

public Helper(IHTMLWindow2 lwin,Class1 obj)

{

leftwin=lwin;

clsobj=obj;

}

public void helperfun()

{

MessageBox.show("leftwin href::"+leftwin.getLocation().getHref());

}

}

Regards,

Sumathi



Answer this question

COM object that has been separated from its underlying RCW cannot be used exception within threads

  • Yaroslav58211

    Hi Sumathi,

    We are investigating this issue. we will keep you Updated. You can try to assign IHTMLWindow without getting it's parent and You can get its Parent in Thread Two.

    Thread one:

    clsobj.leftwin = (IHTMLWindow2)win.getPeer();

    Thread Two:

    MessageBox.show(clsobj.leftwin.getParent().getLocation().getHref());

    Thanks,

    Noorul Ameen.


  • Brad Peterson

    Nope, haven't tried because my problem is with the vs2005 test suite and NOT with asp. Same error, extremely different cause. thanx,mm

  • Morten Hvidberg-Knudsen

    Hi Sumathi,

    I got the same error while running your code. I am investigating the cause of error. Meanwhile you can try the following code if this suits your application needs. I have changed the initDController function slightly and put it in ThreadOne. InitDcontroller function in ThreadOne will initialize the leftwindow object. Now you can access leftwindow in ThreadTwo which is initialized in ThreadOne.

    import com.ms.wfc.html.*;

    import com.ms.wfc.core.*;

    import com.ms.wfc.ui.*;

    import com.ms.wfc.html.om.*;

    public class Class1 extends DhDocument

    {

    public IHTMLWindow2 bottomwin;

    public IHTMLWindow2 leftwin;

    public Helper helperobj;

    public Class1()

    {

    initForm();

    }

    public void dispose()

    {

    super.dispose();

    }

    private void initForm()

    {

    }

    protected void onDocumentLoad(Object sender, Event e)

    {

    try

    {

    bottomwin = this.getWindowPeer().getParent().getParent();

    MessageBox.show("Main Thread:href::" + bottomwin.getLocation().getHref());

    ThreadOne obj1 = new ThreadOne(this);

    Thread thr1 = new Thread(obj1);

    thr1.setApartmentState(System.Threading.ApartmentState.STA);

    thr1.start();

    }

    catch (Exception e1)

    {

    }

    }

    }

    public class ThreadOne implements Runnable

    {

    public Class1 clsobj;

    public ThreadOne(Class1 obj)

    {

    clsobj = obj;

    }

    public void initDController()

    {

    DhWindow win = clsobj.getDocument().getWindow();

    clsobj.leftwin = (IHTMLWindow2)win.getPeer();

    clsobj.helperobj = new Helper(clsobj.leftwin, clsobj);

    ThreadTwo obj2 = new ThreadTwo(clsobj.helperobj, clsobj);

    Thread thr2 = new Thread(obj2);

    thr2.setApartmentState(System.Threading.ApartmentState.STA);

    thr2.start();

    }

    public synchronized void run()

    {

    try

    {

    initDController();

    }

    catch (Exception ex)

    {

    MessageBox.show("exception in thread1::" + ex.toString());

    }

    }

    }

    public class ThreadTwo implements Runnable

    {

    public Class1 clsobj;

    public Helper helperobj;

    public ThreadTwo(Helper hobj, Class1 obj)

    {

    helperobj = hobj;

    clsobj = obj;

    }

    public synchronized void run()

    {

    try

    {

    //this line tries to access the bottomwin which is initialized by main thread

    //it works fine without exception

    MessageBox.show("bottomwin length in thread2::" + clsobj.bottomwin.getLength());

    //next two lines access the leftwin which is initialized by thr1

    //and thr1 is also set to STA

    //these lines give the exception COM object that has been separated from its underlying RCW cannot be used

    helperobj.helperfun();

    MessageBox.show(clsobj.leftwin.getLocation().getHref());

    }

    catch (Exception ex)

    {

    MessageBox.show("exception in thread2::" + ex.toString());

    }

    }

    }

    public class Helper

    {

    public Class1 clsobj;

    public IHTMLWindow2 leftwin;

    public Helper(IHTMLWindow2 lwin, Class1 obj)

    {

    leftwin = lwin;

    clsobj = obj;

    }

    public void helperfun()

    {

    MessageBox.show("leftwin href::" + leftwin.getLocation().getHref());

    }

    }

    Please post back if this does not solve your issue.

    Thanks,

    Noorul Ameen.


  • rhoule

    Did anyone ever figure out how to handle this I have having the same problem doing something similar (testing an app that interacts with Word).
  • RoMoVi

    Hi,

    We are getting that exception in our product and i reproduced that with the sample code here. Actually we need to find a particular frame dynamically in thread1 and assign it to a variable and then we access that in second thread. As i said before, that exception happens when we access the frame in the second thread. I assigned the parent window to leftwin just for simplicity and to reproduce the error. So please let us know if there is anyother way to solve this.

    Regards,

    Sumathi


  • Gabriele38

    Hi mumato,

    I met the same problem when using COM object as static field in my test fixture.

    It seems that the object was automatically disposed after each testmethod's running. By the way,this problem won't happen if I use NUnit instead.



  • darwind

    Hi!

    I have quite the same problem but without even using threads directly. 

    I wrote a library to automate Office Applications (namely Word, Excel, Outlook and PowerPoint) and some unit tests with it. When running these tests piece by piece, they all work well. But when running them whole, there are always some tests that fail with the message "COM object that has been separated from its underlying RCW cannot be used", and the tests that fail are not always the same ones.

    Could it be that there is a timing problem I also realized that that the COM component gets disposed of way immediately after its retrieval...

    CU

      Q


  • Mike Houglum

    Hi,

    Our Team is investigating this issue. We will keep you updated.Thanks for reporting this issue.

    Thanks,

    Noorul Ameen.


  • bkjuice

    I found the answer here: http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=175181&SiteID=1

    Basically you need to switch the unit test to MTA since each unit test runs in its own thread. To do this change the0 to 1 in .testrunconfig so you end up with:

    <apartmentState type="System.Threading.ApartmentState">
    <value__ type="System.Int32">1</value__>
    </apartmentState>


  • cisco0407

    I am also having problems in a similar scenario. I'm trying to run tests for an Outlook add-in and I get the same error message when my class cleanup method runs. It would be nice if I could at least test my code without dramas. :-)

  • saint nik

    I saw this link:

    FIX: "COM Object Can Not Be Used" Error Message When You Use an STA COM Object That You Created by Using Server.CreateObject and Stored in Session Scope in a Different Web Page
    http://support.microsoft.com/kb/818612/

    on this thread:
    http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=493227&SiteID=1

    Have you tried that


  • Nick Foster

    Hi Qanuc, got a solution

    Stepped into the same trap - each test runs for itself but running them all won't work - calling the Tests from a single [TestMethod] (and remove the TestMethod attributes of the tests, keeping it only in the one that calls the 'Tests'), everything works fine...

    What i'm doing is to create a COM Instance of a RealTime Processdata SDK and keeping it in some kind of Singleton (it's a Monostate) - the first Test runs perfectly, in the second test (without calling Marshal.ReleaseComObject(...)) the COM instance is no longer valid.

    Doing the same stuff in NUnit it works fine, no "COM object that has been separated from its underlying RCW cannot be used" only within VS2005 it appears to be a problem.

    Is it possible the Tests in VS 2005 / .NET 2.0 run in separate Threads (whatever that means to a COM Object)

    cu, mumato



  • JainMohit

    Hi,

    Thanks for your help. I tried that as you said, but you seemed to assign the peer element of the window to leftwin,

    DhWindow win = clsobj.getDocument().getWindow();

    clsobj.leftwin = (IHTMLWindow2)win.getPeer();

    but we need to assign parent of the window peer to leftwin,

    leftwin=this.getWindowPeer().getParent();

    It's working if we just assign the peer element of the window without getting parent, in such case it seems to work without modifying the initDController() and having that in Class1.java itself, but the problem happens when we try to access the parent.

    Here i give the order of our frames starting from bottom.html

    bottom.html:

    <BODY topmargin=0 bottommargin=0 leftmargin=0 rightmargin=0 scroll=no>
    <IFRAME name="dleftframe" src="left.html" height="50%" width="50%" APPLICATION="yes" frameborder=0>
    </IFRAME>
    <IFRAME name="webwindows" src="blank.html" height="50%" width="50%" APPLICATION="yes" frameborder=0 >
    </IFRAME>
    </BODY>

    left.html:

    <BODY>
    <IFRAME name="dcontrolframe" src="Page1.htm" height="30%" width="100%" scrolling="yes" APPLICATION="yes">
    </IFRAME>
    </BODY>

    Page1.htm:

    <BODY>

    <OBJECT CLASSID="CLSID:CF83EA5E-0FFD-4476-9BF7-6C15F7F8BDCF" height=0 width=0 … VIEWASTEXT ID="Object1">
    <PARAM NAME=CODECLASS VALUE="DemoThread.dll#Class1">
    <PARAM NAME=VJSVERSION VALUE= 1.0.3710>
    </OBJECT>

    <!-- Insert HTML here -->
    <SPAN id="bindText">This is bound text.</SPAN>
    </BODY>

    So how can we solve this Please reply if you find any solution.

    Regards,

    Sumathi


  • COM object that has been separated from its underlying RCW cannot be used exception within threads