2009-08-09 9 views
3

Je souhaite créer 3 threads qui exécutent chacun le contrôle WebBroswer. Donc, je voudrais utiliser le ThreadPool pour rendre les choses faciles.MultiThreading WebBrowser Control C# STA

for(int i = 0;i < 3;i++) 
{ 
    ThreadPool.QueueUserWorkItem(new WaitCallback(gotoWork), i)); 
} 
WaitAll(waitHandles); 

....../

void gotoWork(object o) 
{ 
    string url = String.Empty; 
    int num = (int)o; 
    switch(num) 
    { 
    case 0: 
     url = "google.com"; 
     break; 
    case 1: 
     url = "yahoo.com"; 
     break; 
    case 2: 
     url = "bing.com"; 
     break; 
    } 
    WebBrowser w = new WebBrower(); 
    w.Navigate(url); 
} 

Mais je reçois une erreur disant que je besoin d'un thread STA qui le ThreadPool ne sera jamais. Avant d'essayer cette méthode, j'ai essayé cela.

Thread[] threads = Thread[3]; 
for(int i = 0;i < 3;i++) 
{ 
    threads[i] = new Thread(new ParameterizedStart(gotoWork); 
    threads[i] = SetApartmentState(ApartmentState.STA); //whoo hoo 
    threads[i] = Start(); 
} 
for(int i = 0; i < 3;i++) 
{ 
    threads[i].Join(); 
} 

Et les webbrowsers tout initialisé et tout semble bon, mais seulement un de plus de deux fera quoi que ce soit et son tout jamais cohérente. Threading a été un tel cauchemar. Quelqu'un peut-il suggérer une bonne alternative?

+0

Pourquoi voulez-vous de charger plusieurs pages à la fois? Avez-vous besoin d'un WebBrowser ou d'un travail HttpWebRequest (par exemple avez-vous besoin de voir la page et/ou avez-vous besoin de JavaScript sur la page pour s'exécuter)? Si vous cherchez à faire de l'exploration/grattage Web, il existe des moyens plus efficaces. – Chad

Répondre

0
public sealed class SiteHelper : Form 
{ 
    public WebBrowser mBrowser = new WebBrowser(); 
    ManualResetEvent mStart; 
    public event CompletedCallback Completed; 
    public SiteHelper(ManualResetEvent start) 
    { 
     mBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(mBrowser_DocumentCompleted); 
     mStart = start; 
    } 
    void mBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) 
    { 
     // Generated completed event 
     Completed(mBrowser); 
    } 
    public void Navigate(string url) 
    { 
     // Start navigating 
     this.BeginInvoke(new Action(() => mBrowser.Navigate(url))); 
    } 
    public void Terminate() 
    { 
     // Shutdown form and message loop 
     this.Invoke(new Action(() => this.Close())); 
    } 
    protected override void SetVisibleCore(bool value) 
    { 
     if (!IsHandleCreated) 
     { 
      // First-time init, create handle and wait for message pump to run 
      this.CreateHandle(); 
      this.BeginInvoke(new Action(() => mStart.Set())); 
     } 
     // Keep form hidden 
     value = false; 
     base.SetVisibleCore(value); 
    } 
} 

Une autre classe

public abstract class SiteManager : IDisposable 
{ 
    private ManualResetEvent mStart; 
    private SiteHelper mSyncProvider; 
    public event CompletedCallback Completed; 

    public SiteManager() 
    { 
     // Start the thread, wait for it to initialize 
     mStart = new ManualResetEvent(false); 
     Thread t = new Thread(startPump); 
     t.SetApartmentState(ApartmentState.STA); 
     t.IsBackground = true; 
     t.Start(); 
     mStart.WaitOne(); 
    } 
    public void Dispose() 
    { 
     // Shutdown message loop and thread 
     mSyncProvider.Terminate(); 
    } 
    public void Navigate(string url) 
    { 
     // Start navigating to a URL 
     mSyncProvider.Navigate(url); 
    } 
    public void mSyncProvider_Completed(WebBrowser wb) 
    { 
     // Navigation completed, raise event 
      CompletedCallback handler = Completed; 
      if (handler != null) 
      { 
       handler(wb); 
      } 
    } 
    private void startPump() 
    { 
     // Start the message loop 
     mSyncProvider = new SiteHelper(mStart); 
     mSyncProvider.Completed += mSyncProvider_Completed; 
     Application.Run(mSyncProvider); 
    } 
} 


class Tester :SiteManager 
{ 
    public Tester() 
    { 
     SiteEventArgs ar = new SiteEventArgs("MeSite"); 

     base.Completed += new CompletedCallback(Tester_Completed); 
    } 

    void Tester_Completed(WebBrowser wb) 
    { 
     MessageBox.Show("Tester"); 
     if(wb.DocumentTitle == "Hi") 

     base.mSyncProvider_Completed(wb); 
    } 

    //protected override void mSyncProvider_Completed(WebBrowser wb) 
    //{ 
    // // MessageBox.Show("overload Tester"); 
    // //base.mSyncProvider_Completed(wb, ar); 
    //} 
} 

Sur votre principale forme:

private void button1_Click(object sender, EventArgs e) 
{ 
    //Tester pump = new Tester(); 
    //pump.Completed += new CompletedCallback(pump_Completed); 
    //pump.Navigate("www.cnn.com"); 

    Tester pump2 = new Tester(); 
    pump2.Completed += new CompletedCallback(pump_Completed); 
    pump2.Navigate("www.google.com"); 
} 
+0

lance-t-il chaque Navigate dans un thread et continue d'exécuter? Si oui, chacun doit-il y avoir un nouvel objet Tester pour chaque thread? – xendi

0

Vous devez héberger le contrôle webbrowser quelque part pour le faire fonctionner (ajoutez-le à un formulaire), ensuite vous devez utiliser Invoke() du contrôle hôte (ou un délégué similaire) tel que Form.Invoke() pour interagir avec le contrôle WebBrowser.

Pas besoin de rappeler maintenant, mais oui, vos fils doivent être STA

0

Vous pouvez utiliser ce type de classe pour votre but d'accueillir le contrôle WebBrowser:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace SomeNameSpace 
{ 
    public class WebForm : Form 
    { 
     public WebBrowser WebBrowser { get; set; } 

     public WebForm() 
     { 
      WebBrowser = new WebBrowser(); 
     } 
    } 
} 
Questions connexes