By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,158 Members | 1,376 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,158 IT Pros & Developers. It's quick & easy.

Threading problem

P: n/a
I need some help to understand a specific threading problem :
I wrote a function "BrowserObjects()" for testing webcontent.

....
IHTMLDocument3 currentDoc = (IHTMLDocument3)ObjectFromLResult(lRes, ref
IID_IHTMLDocument,0);
IHTMLElementCollection frameCol = currentDoc.getElementsByTagName("FRAME");
foreach (IHTMLElement element in frameCol)
{
if (element is IHTMLElement)
{
DispHTMLFrameElement frameElement = (DispHTMLFrameElement)element;
IHTMLWindow2 newWindow = frameElement.contentWindow;
//InvalidCastException, if called in separate thread?
....
}
}
....

no problem, except when I try the following :

Thread secThread = new Thread(new ThreadStart(RunWebTest);
secThread.Start();

public void RunWebTest()
{
...
BrowserObjects();
...
}

as soon as I call the function in a separate thread, it raises a
"InvalidCastException : Schnittstelle wird nicht unterstützt." (german VS
..NET, would be Interface not supported/implemented I guess)

Could someone explain me why this Exception is only raised when I called in
a new thread?
And if it's a general interface/threading problem, why does it never happen
on IHTMLDocument3 ?
Only the call the IHTMLWindow2 raises the exception.

thx :)

Ulf

Nov 16 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
Ulf,

Seems you are trying to to use a COM object created on one thread in
another. It is not allowed to pass COM interfaces between threads - they
should be marshaled instead.
In the unmanaged world, this is done through CoMarshalInterfaceToThread. Not
sure if .NET handles this automatically behind the scenes, so this might be
the case.

Try to create the HTMLDocument instance from scratch on your worker thread.
Also, try to mark your Main method as [MTAThread]

--
Sincerely,
Dmitriy Lapshin [C# / .NET MVP]
Bring the power of unit testing to the VS .NET IDE today!
http://www.x-unity.net/teststudio.aspx

"Ulf Bietz" <ul*@nospam.com> wrote in message
news:cb**********@ngspool-d02.news.aol.com...
I need some help to understand a specific threading problem :
I wrote a function "BrowserObjects()" for testing webcontent.

...
IHTMLDocument3 currentDoc = (IHTMLDocument3)ObjectFromLResult(lRes, ref
IID_IHTMLDocument,0);
IHTMLElementCollection frameCol = currentDoc.getElementsByTagName("FRAME"); foreach (IHTMLElement element in frameCol)
{
if (element is IHTMLElement)
{
DispHTMLFrameElement frameElement = (DispHTMLFrameElement)element;
IHTMLWindow2 newWindow = frameElement.contentWindow;
//InvalidCastException, if called in separate thread?
....
}
}
...

no problem, except when I try the following :

Thread secThread = new Thread(new ThreadStart(RunWebTest);
secThread.Start();

public void RunWebTest()
{
...
BrowserObjects();
...
}

as soon as I call the function in a separate thread, it raises a
"InvalidCastException : Schnittstelle wird nicht unterstützt." (german VS
.NET, would be Interface not supported/implemented I guess)

Could someone explain me why this Exception is only raised when I called in a new thread?
And if it's a general interface/threading problem, why does it never happen on IHTMLDocument3 ?
Only the call the IHTMLWindow2 raises the exception.

thx :)

Ulf


Nov 16 '05 #2

P: n/a
Hi Dmitriy,

thx for your suggestions. I tried MTAThread already, but with no success.
From my understanding, I create and use the COM object in the same thread.
Here is the code :

private void Form1_Load(object sender, System.EventArgs e)
{
Thread secThread = new Thread(new ThreadStart(StartTest));
secThread.Priority = ThreadPriority.Lowest;
secThread.CurrentCulture = new CultureInfo("en-GB",false);
secThread.Start();

//if I run directly
// StartTest() ;
// everything works fine
}

public void StartTest()
{
const int SMTO_ABORTIFHUNG = 0x00000002;

WarObj w = new WarObj(); //library for automated tests

Process proc = new Process();
proc.StartInfo.FileName = "iexplore";
proc.StartInfo.Arguments = "any website";
proc.Start();

int lMsg, lRes = 0, hWnd;

Guid IID_IHTMLDocument = new Guid("626FC520-A41E-11CF-A731-00A0C9082637");

hWnd = w.GetHandle(1,"Internet Explorer_Server");
if (hWnd == 0)
{
MessageBox.Show("Could not find Internet Explorer_Server");
return;
}

lMsg = Win32.RegisterWindowMessage("WM_HTML_GETOBJECT");
Win32.SendMessageTimeout(hWnd,lMsg,0,0,SMTO_ABORTI FHUNG,1000, ref lRes);
if(lRes == 0)
{
MessageBox.Show("Could not send WM_HTML_GETOBJECT message");
return;
}
IHTMLDocument3 myInstance =
(IHTMLDocument3)Win32.ObjectFromLresult(lRes,ref IID_IHTMLDocument,0);
IHTMLElementCollection elements = myInstance.getElementsByTagName("FRAME");

foreach(IHTMLElement element in elements )
{
if(element is IHTMLFrameElement)
{
DispHTMLFrameElement frameElement = (DispHTMLFrameElement)element;
IHTMLWindow2 window = frameElement.contentWindow;
IHTMLDocument2 frameDoc = window.document;
IHTMLElementCollection allTag = frameDoc.all;
foreach(IHTMLElement myTag in allTag)
{
if ((myTag.tagName.Equals("INPUT") || myTag.tagName.Equals("A"))&&
myTag.outerHTML.IndexOf("login")>=0)
{
MessageBox.Show("Login found");
}
}
}
}
proc.Kill();
}

Any hints where I'm wrong ?

thx :)

Ulf

"Dmitriy Lapshin [C# / .NET MVP]" <x-****@no-spam-please.hotpop.com> schrieb
im Newsbeitrag news:uW**************@TK2MSFTNGP09.phx.gbl...
Ulf,

Seems you are trying to to use a COM object created on one thread in
another. It is not allowed to pass COM interfaces between threads - they
should be marshaled instead.
In the unmanaged world, this is done through CoMarshalInterfaceToThread. Not sure if .NET handles this automatically behind the scenes, so this might be the case.

Try to create the HTMLDocument instance from scratch on your worker thread. Also, try to mark your Main method as [MTAThread]

--
Sincerely,
Dmitriy Lapshin [C# / .NET MVP]
Bring the power of unit testing to the VS .NET IDE today!
http://www.x-unity.net/teststudio.aspx

Nov 16 '05 #3

P: n/a
Hi again,
I simply added the ApartmentState :

private void Form1_Load(object sender, System.EventArgs e)
{
Thread secThread = new Thread(new ThreadStart(StartTest));
secThread.Priority = ThreadPriority.Lowest;
secThread.CurrentCulture = new CultureInfo("en-GB",false);
secThread.ApartmentState = ApartmentState.STA;
secThread.Start();
}

works fine now, but I'll still have to spend some hours compulsing MSDN to
understand why :)

Ulf
Nov 16 '05 #4

P: n/a
Ulf,

I am really glad you've resolved the issue. The explanation seems to be as
follows:

Any thread talking to COM should register with the COM subsystem by calling
CoInitialize(). When you start an unmanaged thread and plan to use COM from
it, one of the first calls in the thread routine should be a call to
CoInitialize(). For a .NET Thread, you instruct it to register with COM by
setting its ApartmentState property.

--
Sincerely,
Dmitriy Lapshin [C# / .NET MVP]
Bring the power of unit testing to the VS .NET IDE today!
http://www.x-unity.net/teststudio.aspx

"Ulf Bietz" <ul*@nospam.com> wrote in message
news:cb**********@ngspool-d02.news.aol.com...
Hi again,
I simply added the ApartmentState :

private void Form1_Load(object sender, System.EventArgs e)
{
Thread secThread = new Thread(new ThreadStart(StartTest));
secThread.Priority = ThreadPriority.Lowest;
secThread.CurrentCulture = new CultureInfo("en-GB",false);
secThread.ApartmentState = ApartmentState.STA;
secThread.Start();
}

works fine now, but I'll still have to spend some hours compulsing MSDN to
understand why :)

Ulf


Nov 16 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.