Thread lock on HtmlDocument.InvokeScript

J

jrox6279

Hello,

I have a C# UI Control that allows Google maps to be displayed in a
Windows Form. I am using the WebBrowser control in a secondary thread
to accomplish this. I make several calls to InvokeScript to move,
size, etc. the maps and 99% of the time it works great. However,
occasionally the InvokeScript calls will lock the secondary thread.
This appears to be because of a deadlock in the Google Maps
Javascript. I have added code to my application to abort and restart
the secondary thread, but the thread never actually gets aborted. I
can still see the threads while debugging in the Threads window. I
have a try...catch for the ThreadAbortException in the secondary
thread, but the exception is never thrown. If I call Join() on the
Thread after calling Abort(), the Join() never returns.

I need a way to either call InvokeScript with a timeout or
asynchronously, or kill the thread completely. Any help would be
greatly appreciated.

Thanks,
Josh
 
J

Jon Skeet [C# MVP]

I have a C# UI Control that allows Google maps to be displayed in a
Windows Form. I am using the WebBrowser control in a secondary thread
to accomplish this.

That sounds like a bad idea to start with. Just to check what you
mean, this WebBrowser has been created in one thread but you're
calling methods on it from a different thread? That's generally a no-
no with UI controls - do you have anything to suggest that should
wait?
I make several calls to InvokeScript to move,
size, etc. the maps and 99% of the time it works great. However,
occasionally the InvokeScript calls will lock the secondary thread.
This appears to be because of a deadlock in the Google Maps
Javascript. I have added code to my application to abort and restart
the secondary thread, but the thread never actually gets aborted.

You shouldn't use Thread.Abort - it's unsafe.

Jon
 
J

jrox6279

Thanks for the reply, Jon. I am using the BeginInvoke, EndInvoke, and
AsyncWaitHandle methods to call from the main thread to the secondary
thread. If the AsyncWaitHandle does not return in 2.5 seconds, I
abort the thread.

Unfortunately, I don't know any other way to get around the deadlocak
other than creating a new thread, and I would like to get rid of the
old thread, if possible. I would like to trigger and event or some
other signal to cause the thread to shutdown, however since the thread
is locked it will not receive any signals. I assume the
ThreadAbortException is also not received because the thread is
locked.

If there was a way to call InvokeScript with a timeout, or
asynchornously that would be great, but so far I have been unable to
find such a function. Without such a function and since I am using
someone else code, the only other option I know of is to abort the
thread (if that were possible).

Thanks,
Josh
 
N

Nicholas Paldino [.NET/C# MVP]

Josh,

The way I read this, it seems you have created a WebBrowser on another
thread (without pumping messages, which I assume you are NOT doing), the
entire behavior of the control is not supported.

You ^have^ to create the web browser control on a thread that pumps
windows messages (the static Run method does this on the Application class)
and then marshal all calls to that thread.

Then again, from your response to Jon, it seems like you could be
creating it on the UI thread and then making the calls back into the UI
thread.

However, the WebBrowser control is really a wrapper around unmanaged
code. Because of that, you aren't going to be able to abort a call to most
of it (that is unmanaged). The CLR doesn't honor aborts when the code that
is running on the thread is unmanaged.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Thanks for the reply, Jon. I am using the BeginInvoke, EndInvoke, and
AsyncWaitHandle methods to call from the main thread to the secondary
thread. If the AsyncWaitHandle does not return in 2.5 seconds, I
abort the thread.

Unfortunately, I don't know any other way to get around the deadlocak
other than creating a new thread, and I would like to get rid of the
old thread, if possible. I would like to trigger and event or some
other signal to cause the thread to shutdown, however since the thread
is locked it will not receive any signals. I assume the
ThreadAbortException is also not received because the thread is
locked.

If there was a way to call InvokeScript with a timeout, or
asynchornously that would be great, but so far I have been unable to
find such a function. Without such a function and since I am using
someone else code, the only other option I know of is to abort the
thread (if that were possible).

Thanks,
Josh
 
J

jrox6279

Nicholas,

Thanks for the reply. I do have a message pump running on the
secondary thread (and main thread, of course), and I am using
delegates and events to call from the main thread to the secondary
thread. If the Thread.Abort() function does not work when native code
is being run, is there a native call or another call that I could make
to shut the thread down?

From what I have read and what you said, I am thinking the only way
around this is to some how make my javascript calls asynchronous.
Unfortunately, this would probably be a good deal of work. Any other
options?

Thanks,
Josh

Josh,

    The way I read this, it seems you have created a WebBrowser on another
thread (without pumping messages, which I assume you are NOT doing), the
entire behavior of the control is not supported.

    You ^have^ to create the web browser control on a thread that pumps
windows messages (the static Run method does this on the Application class)
and then marshal all calls to that thread.

    Then again, from your response to Jon, it seems like you could be
creating it on the UI thread and then making the calls back into the UI
thread.

    However, the WebBrowser control is really a wrapper around unmanaged
code.  Because of that, you aren't going to be able to abort a call to most
of it (that is unmanaged).  The CLR doesn't honor aborts when the code that
is running on the thread is unmanaged.

--
          - Nicholas Paldino [.NET/C# MVP]
          - (e-mail address removed)


Thanks for the reply, Jon.  I am using the BeginInvoke, EndInvoke, and
AsyncWaitHandle methods to call from the main thread to the secondary
thread.  If the AsyncWaitHandle does not return in 2.5 seconds, I
abort the thread.

Unfortunately, I don't know any other way to get around the deadlocak
other than creating a new thread, and I would like to get rid of the
old thread, if possible.  I would like to trigger and event or some
other signal to cause the thread to shutdown, however since the thread
is locked it will not receive any signals.  I assume the
ThreadAbortException is also not received because the thread is
locked.

If there was a way to callInvokeScriptwith a timeout, or
asynchornously that would be great, but so far I have been unable to
find such a function.  Without such a function and since I am using
someone else code, the only other option I know of is to abort the
thread (if that were possible).

Thanks,
Josh

On Jan 25, 4:40 pm, (e-mail address removed) wrote:
That sounds like a bad idea to start with. Just to check what you
mean, this WebBrowser has been created in one thread but you're
calling methods on it from a different thread? That's generally a no-
no with UI controls - do you have anything to suggest that should
wait?
You shouldn't use Thread.Abort - it's unsafe.
Jon- Hide quoted text -

- Show quoted text -
 
N

Nicholas Paldino [.NET/C# MVP]

Josh,

Admittedly, I loathe the idea of saying this, but in this case, you
might want to move your processing to the UI thread and then make calls to
DoEvents (off the Application class) in order to keep your UI somewhat
responsive.

Making a call to another thread to abort the thread is most definitely a
bad idea. It's not guaranteed that the same physical thread will be used in
..NET to process different threads. By going and trying to kill the physical
thread, you could introduce other issues.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Nicholas,

Thanks for the reply. I do have a message pump running on the
secondary thread (and main thread, of course), and I am using
delegates and events to call from the main thread to the secondary
thread. If the Thread.Abort() function does not work when native code
is being run, is there a native call or another call that I could make
to shut the thread down?

From what I have read and what you said, I am thinking the only way
around this is to some how make my javascript calls asynchronous.
Unfortunately, this would probably be a good deal of work. Any other
options?

Thanks,
Josh

Josh,

The way I read this, it seems you have created a WebBrowser on another
thread (without pumping messages, which I assume you are NOT doing), the
entire behavior of the control is not supported.

You ^have^ to create the web browser control on a thread that pumps
windows messages (the static Run method does this on the Application
class)
and then marshal all calls to that thread.

Then again, from your response to Jon, it seems like you could be
creating it on the UI thread and then making the calls back into the UI
thread.

However, the WebBrowser control is really a wrapper around unmanaged
code. Because of that, you aren't going to be able to abort a call to most
of it (that is unmanaged). The CLR doesn't honor aborts when the code that
is running on the thread is unmanaged.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Thanks for the reply, Jon. I am using the BeginInvoke, EndInvoke, and
AsyncWaitHandle methods to call from the main thread to the secondary
thread. If the AsyncWaitHandle does not return in 2.5 seconds, I
abort the thread.

Unfortunately, I don't know any other way to get around the deadlocak
other than creating a new thread, and I would like to get rid of the
old thread, if possible. I would like to trigger and event or some
other signal to cause the thread to shutdown, however since the thread
is locked it will not receive any signals. I assume the
ThreadAbortException is also not received because the thread is
locked.

If there was a way to callInvokeScriptwith a timeout, or
asynchornously that would be great, but so far I have been unable to
find such a function. Without such a function and since I am using
someone else code, the only other option I know of is to abort the
thread (if that were possible).

Thanks,
Josh

On Jan 25, 4:40 pm, (e-mail address removed) wrote:
That sounds like a bad idea to start with. Just to check what you
mean, this WebBrowser has been created in one thread but you're
calling methods on it from a different thread? That's generally a no-
no with UI controls - do you have anything to suggest that should
wait?
You shouldn't use Thread.Abort - it's unsafe.
Jon- Hide quoted text -

- Show quoted text -
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top