0

I have looked around but I am having difficulty finding a way to implement the following:

I have a WPF application with has a web browser control. I have a file saved on disk, and I am using the Navigate method to load the file.

I have an event handler attached to the web browser LoadCompleted event, and this works.

However, pages can take a long time to load. I want to display a progress bar (ideally in a status bar, but a new window is okay), but I can't find anyway to do this.

Every thing I have tried (background workers, threads) all say that the calling thread must be STA, and it seems that the progress bar, being a UI element, can only be updated on the UI thread - which is blocked by the web browser control during rendering of a page.

Alternatively is there a way to run the web browser control in a new thread? I am guessing not as this is also a UI element.

Any help would be appreciated.

p.s. The progress bar is a simple indeterminate bar; I am not trying to update the status - just display whilst a page is being loaded.

Nigel Ellis
  • 601
  • 1
  • 8
  • 18
  • http://msdn.microsoft.com/en-us/library/ms144190.aspx – paparazzo Mar 25 '14 at 12:47
  • It's not the downloading of the data that is the problem; the web browser control blocks the thread until it has download the data and displayed it. And being html this could lead to other items such as images and javascript/css. – Nigel Ellis Mar 25 '14 at 13:38

1 Answers1

0

All UI controls will insist that they are updated only by the UI thread. This is standard in both WinForms and WPF. In WPF, this thread marshalling is done using the Dispatcher, preferably the one used to create the control but if a reference to the control is not available (say, in an MVVM environment, The Application Dispatcher will do fine.)

The usual pattern for updating an UI element from another thread using the Dispatcher is

private void UpdateStatusBar(int progress)
{
    if (!Application.Current.Dispatcher.CheckAccess())
    {
        Application.Current.Dispatcher.Invoke(() => UpdateStatusBar(progress));
        return;
    }

    // update status here
}
Barracoder
  • 3,696
  • 2
  • 28
  • 31
  • I am not trying to update from another thread. At the moment I have one thread, but the progress bar stops whilst the web browser is doing its work. I am trying to move either the progress bar or the web browser control to a different thread so the progress bar can update. One thing I may not have been clear about is when I saw update the progress bar I mean redraw, as it stops/pauses whilst the web browser renders the page. – Nigel Ellis Mar 25 '14 at 13:51
  • Then I'd suggest running the WebBrowser Navigation on one thread and arbitrarily updating the progress bar on another thread and finishing the progress when the WebBrowser.LoadCompleted event is fired. – Barracoder Mar 25 '14 at 14:46
  • Do you have any examples of how to run the Navigation on a separate thread? At the moment my code is just WebBrowser.Navigate(fileName); – Nigel Ellis Mar 25 '14 at 14:48
  • I tried the answer from http://stackoverflow.com/questions/8645926/how-to-create-and-use-webbrowser-in-background-thread - but this still seems to have the same problem. The web browser loads, but as it does it stops the progress bar from being redrawn. – Nigel Ellis Mar 25 '14 at 15:39
  • Have you tried WebBrowser.Dispatcher.BeginInvoke(() => WebBrowser.Navigate(filename));? That's probably the simplest way. – Barracoder Mar 25 '14 at 16:15
  • I have now, and that hasn't changed anything; the web browser downloads, the mouse pointer changes to a scrolling ring, but the progress bar does not redraw. – Nigel Ellis Mar 25 '14 at 16:21