471,123 Members | 860 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,123 software developers and data experts.

Shdocvw, multithreading - COMException

**** sorry about the length of the message. If you can't read the
whole thing and still willing to help, read the last 2 paragraphs where
the main problem is described. The introduction story is mentioned to,
as much clear as possible, give a picture in what environment the
problems rise****
Hello experts!
I would appreciate if you can address this problem I have and give a
hint what could be wrong.

It's a Windows Form application in VB.NET that uses shdocvw.dll to
automate internet browsing. I use InternetExplorer class from this
library. Navigation, browsing, setting the field values on the page,
submitting the forms and collecting the information is supposed to
happen all the time, in the loop. Once there are no more requests,
program will shut down. Let's call this app. the "worker".
This part works fine. Also I need to control this application from
within the other winform program, using .NET Remoting. For example, two
typical tasks would be query the information (like current state) and
close (force the shutdown of) the "worker". Let's call this app.
the "foreman". So "foreman" controls the execution of multiple
"worker" instances.
Because of the "worker" might be interrupted in it's job by
"foreman", I figured I should put it's main execution in the
background thread. So loop is executing in the bkg. thread and during
that time the .NET Remoting call for querying the info works fine.
Whatever the "worker" is doing, it's internal browser busy
navigating or idle, this call works. But when the "foreman" tries
to send the command for shutdown, most often the problems rise, usually
the COMException. The request to shutdown works like this:
"foreman" sends the .NET Remoting request to the "worker" and
the "worker" executes the simple Me.Close (since it's the winform
app). Then in the Window_Closing event handler some cleanup needs to be
done, first stop the browsing if currently in browsing mode, then
logout from the website, etc. As I understand, .NET Remoting call will
create a separate thread in the "worker" app, so the problems that
occur have something to do with multithreading and COM.
Since the error message wasn't always the same and the behavior not
unique every time, it's hard for me to describe what exactly happen.
Especially because multiple apps are executing and I can't debug them
all at the same time. Therefore I experiment with the "worker" only
and I managed to get the same error every time, that I'll describe
here. I hope it hapens for the same reason (multithreading with COM in
it) so if you give me a good advice, I'll probably be able to apply
it in the multi-app mode.

So here it is, very shortly:
"worker" processes the requests in a loop, internal IE object is
browsing, everything happens in a background thread. When all the work
is done, "worker" calls Me.Close on itself, this command still
happens in the bkg. thread. But once the Window_Closing ev. handler
starts executing, I notice this happens in a new thread. OK, that makes
sense, but it seems it causes the problems, because from this thread
some more IE browsing needs to be done, namely the logout from the
website. But as soon as the IE is invoked, even to access it's
Document property (not even to perform the action), the COM Exception
rises. I wonder why??? It's true that the COM object is accessed from
another thread, but at this moment IE is idle, it's not browsing or
doing anything. Maybe I need to mention, IE object is not even created
in the main bkg. thread, but during the initialization, in the form's
constructor.

And maybe most important, the COM Exception message:
"System.Runtime.InteropServices.COMException:
An outgoing call cannot be made since the application is dispatching an
input-synchronous call."

Please give a hint how to work-around this problem. Thanks a lot!
Shone

Nov 21 '05 #1
2 3580
When all the work
is done, "worker" calls Me.Close on itself, this command still
happens in the bkg. thread.
You're not allowed to use a Form from a thread other than the one it
was created on. You can use the Invoke or BeginInvoke methods to
execute a method on the UI thread.

But as soon as the IE is invoked, even to access it's
Document property (not even to perform the action), the COM Exception
rises. I wonder why??? It's true that the COM object is accessed from
another thread, but at this moment IE is idle, it's not browsing or
doing anything.
Whether it's idle or not is probably irrelevant here.

Maybe I need to mention, IE object is not even created
in the main bkg. thread, but during the initialization, in the form's
constructor.
Then you shouldn't use from the background thread.

Please give a hint how to work-around this problem. Thanks a lot!


There's no simple workaround. You have to be careful not to use
objects with thread affinity from the wrong thread.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Nov 21 '05 #2
Thanks Mattias.

Your advice helped a lot in a way that now I understand what's allowed
what not, when designing the multithread solution. Now I better
understand the use of Invoke/BeginInvoke and delegates.
There are not too many cross-threads calls in my app, so I'll be able
to modify them all to be executed correctly (from the right thread).
However, I still don't know how to make a call to be executed in the
background thread, the one the browser COM object is working in.
More precisely:
I have a custom class object MyBrowser that contains the
Shdocvw.InternetExplorer object used for automated internet browsing.
All the browsing and the rest of work related to MyBrowser is done in
the background thread. Even the creation of this object is done in the
bkg. thread. Now when the call comes in, either from user or through
..NET Remoting, to interrupt the work and close the app, that call is
handled in the main UI thread. From this thread I need to do some more
browsing (website logout). I would gladly like to do it in a correct
thread, but how can I make the program do that? I can declare a
delegate in MyBrowser class, but I can't call "Invoke" since this class
doesn't implement it. As far as I understand, only Control and derived
classes can use "Invoke"/"BeginInvoke"

Thanks again.

Shone

Nov 21 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by Damaji Jambhale | last post: by
3 posts views Thread by Wiktor Zychla | last post: by
2 posts views Thread by Or Lavy | last post: by
reply views Thread by SLE | last post: by
3 posts views Thread by Jay A. Moritz | last post: by
5 posts views Thread by SQACSharp | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.