2014-01-13 4 views
1

У меня есть кнопка, которая перемещается по веб-странице. Я пытался установить навигацию в фоновой рабочей среде, но она не перемещается. Если я поместил его в событие нажатия кнопки, он отлично работает. Я поставил точку останова в bgw_DoWork, и он показывает, что он достигает точки создания нового объекта wb, однако он пропускает остальные инструкции в DoWork. Я хотел сделать это, чтобы отображать загрузочный образ, когда он пытается получить данные с веб-страницы. Объект webbrowser не является частью пользовательского интерфейса, так как пользователю не нужно видеть скребок. Он просто загружает информацию в объект, а затем отображает объект (за пределами BackgroundWorker).BackgroundWorker в WPF не работает

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Threading; 
using System.Windows; 
using System.Windows.Threading; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.Reflection; 
using System.ComponentModel; 
using mshtml; 

namespace WPF1 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 


     WebBrowser wb; 
     private readonly BackgroundWorker bgw = new BackgroundWorker(); 

     public int i = 0; 

     public MainWindow() 
     { 
      InitializeComponent(); 
      bgw.DoWork += bgw_DoWork; 
      bgw.RunWorkerCompleted += bgw_RunWorkerCompleted; 

     } 

     private void GetSICData_Click(object sender, RoutedEventArgs e) 
     { 
      //mainTabControl.SelectedIndex = 1; 

      //wb.Navigated += wb_Navigated; 
      //wb.LoadCompleted += wb_LoadCompleted; 
      //wb.Navigate("http://www.google.com"); 

      bgw.RunWorkerAsync(); 

     } 

     private void bgw_DoWork(object sender, DoWorkEventArgs e) 
     { 
      wb = new WebBrowser(); 

      wb.Navigated += wb_Navigated; 
      wb.LoadCompleted += wb_LoadCompleted; 
      wb.Navigate("http://www.google.com"); 

     } 

     private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      MessageBox.Show("Background Complete"); 
     } 

     void wb_LoadCompleted(object sender, NavigationEventArgs e) 
     { 

      HTMLDocument doc = (HTMLDocument)wb.Document; 
      doc.getElementById("ctl03_TextBox1").innerText = "2334882"; 

      wb.LoadCompleted -= wb_LoadCompleted; 
      wb.LoadCompleted += wb_LoadCompleted_2; 

      doc.getElementById("ImageButton1").click(); 

     } 

     void wb_LoadCompleted_2(object sender, NavigationEventArgs e) 
     { 
      MessageBox.Show("It Worked!"); 
     } 

     void wb_Navigated(object sender, NavigationEventArgs e) 
     { 

     } 

    } 
} 
+4

Вы не можете управлять элементами пользовательского интерфейса в фоновом потоке –

+0

Есть ли способ создать объект webbrowser, который не является частью пользовательского интерфейса? – user3175176

+2

@ user3175176 Возможно, вам не следует использовать WebBrowser, если вы не хотите отображать его как часть пользовательского интерфейса, вместо этого вы, вероятно, должны использовать другие классы, которые предназначены для загрузки содержимого веб-сайта без их отображения. – Servy

ответ

3

Это походит на то, что вы действительно хотите это WebClient Class. Вы можете использовать несколько своих методов для загрузки либо всей веб-страницы в виде файла, либо как string. Самое приятное то, что вы также можете сделать это асинхронно, так что все это произойдет в фоновом потоке автоматически.

При использовании этих асинхронных методов вам необходимо обработать соответствующее событие Download...Completed для получения результатов. С DownloadStringCompletedEventHandler Delegate страницы на MSDN:

public static void DownloadStringInBackground2 (string address) 
{ 
    WebClient client = new WebClient(); 
    Uri uri = new Uri(address); 

    // Specify that the DownloadStringCallback2 method gets called 
    // when the download completes. 
    client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(
DownloadStringCallback2); 
    client.DownloadStringAsync (uri); 
} 

private static void DownloadStringCallback2 (Object sender, 
DownloadStringCompletedEventArgs e) 
{ 
    // If the request was not canceled and did not throw 
    // an exception, display the resource. 
    if (!e.Cancelled && e.Error == null) 
    { 
     string textString = (string)e.Result; 

     Console.WriteLine (textString); 
    } 
} 

Взгляните на WebClient.DownloadStringAsync Method и WebClient.DownloadFileAsync Method страниц на веб-сайте MSDN для получения дополнительной информации.

-1

Некоторые из операций пользовательского интерфейса требуют вызова в потоке пользовательского интерфейса. Попробуйте

private void bgw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     wb.Navigated += wb_Navigated; 
     wb.LoadCompleted += wb_LoadCompleted; 

     wb.Dispatcher.Invoke(() => 
     { 

      wb.Navigate("http://www.google.com"); 
     }); 
    } 
+0

Нет смысла использовать BGW в первую очередь, если вы ничего не делаете, кроме как ссылаться на поток пользовательского интерфейса внутри него. – Servy

+0

Да, вы правы. Я просто пытаюсь понять, но должен уделить больше внимания образцу кода.В любом случае, WebClient звучит как лучшая идея. –

0

Вы не можете создать элемент управления пользовательского интерфейса в фоновом потоке, и в этом случае вам не нужно, потому что все WebBrowser методы, которые вы должны выполняются асинхронно в любом случае ...

WebBrowser.Navigate

Переход асинхронно к документу в указанном Uri.

Кстати, не забудьте использовать Navigate метод после того, как элемент управления будет загружен WebBrowser так либо использовать IsLoaded, чтобы проверить или позвонить Navigate из Loaded события ...

Смежные вопросы