tags:

views:

36

answers:

1

I believe the WebBrowser control is STA and a WCFservice hosted in a NT Service is MTA ? Thanks.

+3  A: 

Right, this likely will not work. The WebBrowser control was meant to be used by a single STA thread. It won't map well to MTA in a web service, and will likely require some major hackery.

What are you trying to do? If you can describe your problem, we may be able to come up with an alternative solution.


edit

Ok, this is probably possible, although certainly hacky. Here's a theoretical implementation:

  1. Spin up an STA thread, have the web service thread wait for it.
  2. Load the browser in the STA thread.
  3. Navigate to the desired web page. When navigation finishes, take the screenshot.
  4. Send the screenshot back to web service thread.

The code would look something like this:

public Bitmap GiveMeScreenshot()
{
    var waiter = new ManualResetEvent();
    Bitmap screenshot = null;

    // Spin up an STA thread to do the web browser work:
    var staThread = new Thread(() =>
    {
        var browser = new WebBrowser();
        browser.DocumentCompleted += (sender, e) => 
        {
            screenshot = TakeScreenshotOfLoadedWebpage(browser);
            waiter.Set(); // Signal the web service thread we're done.
        }
        browser.Navigate("http://www.google.com");
    };
    staThread.SetApartmentState(ApartmentState.STA);
    staThread.Start();

    var timeout = TimeSpan.FromSeconds(30);
    waiter.WaitOne(timeout); // Wait for the STA thread to finish.
    return screenshot;
};

private Bitmap TakeScreenshotOfLoadedWebpage(WebBrowser browser)
{
    // TakeScreenshot() doesn't exist. But you can do this using the DrawToDC method:
    // http://msdn.microsoft.com/en-us/library/aa752273(VS.85).aspx
    return browser.TakeScreenshot(); 
}

Also, a note from past experience: we've seen issues where the System.Windows.Forms.WebBrowser doesn't navigate unless it's added to a visual parent, e.g. a Form. Your mileage may vary. Good luck!

Judah Himango
What I want to do is to have the WCF service to render an html page and grab a snapshot and save it to the disk. Thanks.
Frederic Torres
Ok. It's possible to do, just will likely be a bit of a pain in the ass to get working right. I'm updating my answer to include a theoretical implementation.
Judah Himango
I've updated my answer to include a possible solution, hackish as it is.
Judah Himango
Should we call SetApartmentState(ApartmentState.STA) on the thread ? What about running the Windows message pump to process event like DocumentCompleted ?
Frederic Torres
Oh, right, that needs to be set to STA, woops. :-) I'll update the post. You shouldn't need anything beyond that.
Judah Himango