I've created a new WebBrowser() control in a new Thread().
The problem I'm having, is that when invoking a delegate for my WebBrowser from the Main Thread, the call is occurring on the Main Thread. I would expect this to happen on browserThread.
private static WebBrowser defaultApiClient = null;
delegate void DocumentNavigator(string url);
private WebApi() {
// Create a new thread responsible
// for making API calls.
Thread browserThread = new Thread(() => {
defaultApiClient = new WebBrowser();
// Setup our delegates
documentNavigatorDelegate = new DocumentNavigator(defaultApiClient.Navigate);
// Anonymous event handler
defaultApiClient.DocumentCompleted += (object sender, WebBrowserDocumentCompletedEventArgs e) => {
// Do misc. things
};
Application.Run();
});
browserThread.SetApartmentState(ApartmentState.STA);
browserThread.Start();
}
DocumentNavigator documentNavigatorDelegate = null;
private void EnsureInitialized() {
// This always returns "false" for some reason
if (defaultApiClient.InvokeRequired) {
// If I jump ahead to this call
// and put a break point on System.Windows.Forms.dll!System.Windows.Forms.WebBrowser.Navigate(string urlString, string targetFrameName, byte[] postData, string additionalHeaders)
// I find that my call is being done in the "Main Thread".. I would expect this to be done in "browserThread" instead
object result = defaultApiClient.Invoke(documentNavigatorDelegate, WebApiUrl);
}
}
I've tried invoking the method a myriad of ways:
// Calls on Main Thread (as expected)
defaultApiClient.Navigate(WebApiUrl);
// Calls on Main Thread
defaultApiClient.Invoke(documentNavigatorDelegate, WebApiUrl);
// Calls on Main Thread
defaultApiClient.BeginInvoke(documentNavigatorDelegate, WebApiUrl);
// Calls on Main Thread
documentNavigatorDelegate.Invoke(WebApiUrl);
// Calls on random Worker Thread
documentNavigatorDelegate.BeginInvoke(WebApiUrl, new AsyncCallback((IAsyncResult result) => { .... }), null);
Update
Let me break down my end-goal a little bit to make things more clear: I have to make calls using WebBrowser.Document.InvokeScript()
, however Document is not loaded until after I call WebBrowser.Navigate()
and THEN the WebBrowser.DocumentComplete
event fires. Essentially, I cannot make my intended call to InvokeScript()
until after DocumentComplete
fires... I would like to WAIT for the document to load (blocking my caller) so I can call InvokeScript
and return my result in a synchronous fashion.
Basically I need to wait for my document to complete and the way I would like to do that is with a AutoResetEvent()
class which I will trigger upon DocumentComplete being fired... and I need all this stuff to happen in a separate thread.
The other option I see is doing something like this:
private bool initialized = false;
private void EnsureInitialized(){
defaultApiClient.Navigate(WebApiUrl);
while(!initialized){
Thread.Sleep(1000); // This blocks so technically wouldn't work
}
}
private void defaultApiClient_DocumentComplete(object sender, WebBrowserDocumentCompletedEventArgs e){
initialized = true;
}
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…