2010-11-24 17 views
70

मेरे पास एक सूची है उरी है कि मैं इसे प्राप्त करने के लिए "क्लिक" करना चाहता हूं। मैं उरी प्रति नया वेब ब्राउज़र नियंत्रण बनाने की कोशिश कर रहा हूं। मैं उरी प्रति नया धागा बना देता हूं। समस्या मैं ' मीटर होने धागा अंत से पहले दस्तावेज़ पूरी तरह से भरी हुई है, तो मैं कभी नहीं DocumentComplete घटना का उपयोग करना। मैं इस पर काबू पाने कर सकते हैं कैसे मिलता है?वेबब्राउज़र नियंत्रण एक नए धागे में

var item = new ParameterizedThreadStart(ClicIt.Click); 
var thread = new Thread(item) {Name = "ClickThread"}; 
thread.Start(uriItem); 

public static void Click(object o) 
{ 
    var url = ((UriItem)o); 
    Console.WriteLine(@"Clicking: " + url.Link); 
    var clicker = new WebBrowser { ScriptErrorsSuppressed = true }; 
    clicker.DocumentCompleted += BrowseComplete; 
    if (String.IsNullOrEmpty(url.Link)) return; 
    if (url.Link.Equals("about:blank")) return; 
    if (!url.Link.StartsWith("http://") && !url.Link.StartsWith("https://")) 
     url.Link = "http://" + url.Link; 
    clicker.Navigate(url.Link); 
} 

उत्तर

132

आप एक जाँच धागा कि संदेश पाश पंप बनाना होगा। WebBrowser जैसे ActiveX घटक के लिए यह एकमात्र अतिथिमंडल वातावरण है। आपको अन्यथा दस्तावेज़ पूर्ण घटना नहीं मिलेगी। कुछ नमूना कोड:

private void runBrowserThread(Uri url) { 
    var th = new Thread(() => { 
     var br = new WebBrowser(); 
     br.DocumentCompleted += browser_DocumentCompleted; 
     br.Navigate(url); 
     Application.Run(); 
    }); 
    th.SetApartmentState(ApartmentState.STA); 
    th.Start(); 
} 

void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { 
    var br = sender as WebBrowser; 
    if (br.Url == e.Url) { 
     Console.WriteLine("Natigated to {0}", e.Url); 
     Application.ExitThread(); // Stops the thread 
    } 
} 
+0

क्या यह एक WPF एप्लिकेशन के अंदर किया जा सकता है? – Para

+6

हां! बस System.Windows.Forms जोड़ें। मेरा दिन भी बचाया। धन्यवाद – zee

+2

मैं इस स्थिति को अपनी स्थिति में अनुकूलित करने की कोशिश कर रहा हूं। मुझे 'WebBrowser 'ऑब्जेक्ट को जीवित रखना है (राज्य/कुकीज़ आदि को बचाने के लिए) और समय के साथ कई' नेविगेट() 'कॉल करें। लेकिन मुझे यकीन नहीं है कि मेरा 'एप्लिकेशन। रुन()' कॉल कहां रखा जाए, becuz यह निष्पादन से आगे कोड को अवरुद्ध करता है। कोई सुराग? – dotNET

2

अतीत webbrowser ऑपरेटिंग पसंद नहीं करता है में मेरे अनुभव से मुख्य अनुप्रयोग धागे के बाहर।

इसके बजाए httpwebrequests का उपयोग करने का प्रयास करें, आप उन्हें एसिंक्रोनस के रूप में सेट कर सकते हैं और प्रतिक्रिया के लिए एक हैंडलर बना सकते हैं जब यह सफल होता है cesfull:

how-to-use-httpwebrequest-net-asynchronously

+0

इसके साथ मेरी समस्या यह है। उड़ी को क्लिक करने के लिए साइट को लॉग इन करने की आवश्यकता है। मैं इसे WebRequest के साथ प्राप्त नहीं कर सकता। WebBrowser का उपयोग करके यह पहले से ही आईई कैश का उपयोग करता है, इसलिए लॉग इन साइटें। क्या इसके आसपास कोई रास्ता है? लिंक फेसबुक शामिल हैं। तो क्या मैं फेसबुक में लॉग इन कर सकता हूं और webwrequest के साथ लिंक पर क्लिक कर सकता हूं? –

22

यहाँ कैसे WebBrowser स्वचालन तरह अतुल्यकालिक कार्यों को चलाने के लिए, एक गैर यूआई धागे पर संदेश पाश व्यवस्थित करने के लिए है। यह सुविधाजनक रैखिक कोड प्रवाह प्रदान करने के लिए async/await का उपयोग करता है और एक लूप में वेब पृष्ठों का एक सेट लोड करता है। कोड एक तैयार-टू-रन कंसोल ऐप है जो आंशिक रूप से this excellent post पर आधारित है।

संबंधित जवाब:

using System; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Windows.Forms; 

namespace ConsoleApplicationWebBrowser 
{ 
    // by Noseratio - https://stackoverflow.com/users/1768303/noseratio 
    class Program 
    { 
     // Entry Point of the console app 
     static void Main(string[] args) 
     { 
      try 
      { 
       // download each page and dump the content 
       var task = MessageLoopWorker.Run(DoWorkAsync, 
        "http://www.example.com", "http://www.example.net", "http://www.example.org"); 
       task.Wait(); 
       Console.WriteLine("DoWorkAsync completed."); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("DoWorkAsync failed: " + ex.Message); 
      } 

      Console.WriteLine("Press Enter to exit."); 
      Console.ReadLine(); 
     } 

     // navigate WebBrowser to the list of urls in a loop 
     static async Task<object> DoWorkAsync(object[] args) 
     { 
      Console.WriteLine("Start working."); 

      using (var wb = new WebBrowser()) 
      { 
       wb.ScriptErrorsSuppressed = true; 

       TaskCompletionSource<bool> tcs = null; 
       WebBrowserDocumentCompletedEventHandler documentCompletedHandler = (s, e) => 
        tcs.TrySetResult(true); 

       // navigate to each URL in the list 
       foreach (var url in args) 
       { 
        tcs = new TaskCompletionSource<bool>(); 
        wb.DocumentCompleted += documentCompletedHandler; 
        try 
        { 
         wb.Navigate(url.ToString()); 
         // await for DocumentCompleted 
         await tcs.Task; 
        } 
        finally 
        { 
         wb.DocumentCompleted -= documentCompletedHandler; 
        } 
        // the DOM is ready 
        Console.WriteLine(url.ToString()); 
        Console.WriteLine(wb.Document.Body.OuterHtml); 
       } 
      } 

      Console.WriteLine("End working."); 
      return null; 
     } 

    } 

    // a helper class to start the message loop and execute an asynchronous task 
    public static class MessageLoopWorker 
    { 
     public static async Task<object> Run(Func<object[], Task<object>> worker, params object[] args) 
     { 
      var tcs = new TaskCompletionSource<object>(); 

      var thread = new Thread(() => 
      { 
       EventHandler idleHandler = null; 

       idleHandler = async (s, e) => 
       { 
        // handle Application.Idle just once 
        Application.Idle -= idleHandler; 

        // return to the message loop 
        await Task.Yield(); 

        // and continue asynchronously 
        // propogate the result or exception 
        try 
        { 
         var result = await worker(args); 
         tcs.SetResult(result); 
        } 
        catch (Exception ex) 
        { 
         tcs.SetException(ex); 
        } 

        // signal to exit the message loop 
        // Application.Run will exit at this point 
        Application.ExitThread(); 
       }; 

       // handle Application.Idle just once 
       // to make sure we're inside the message loop 
       // and SynchronizationContext has been correctly installed 
       Application.Idle += idleHandler; 
       Application.Run(); 
      }); 

      // set STA model for the new thread 
      thread.SetApartmentState(ApartmentState.STA); 

      // start the thread and await for the task 
      thread.Start(); 
      try 
      { 
       return await tcs.Task; 
      } 
      finally 
      { 
       thread.Join(); 
      } 
     } 
    } 
} 
+1

उस शानदार और सूचनात्मक उत्तर के लिए धन्यवाद! यह वही है जो मैं खोज रहा था। हालांकि आपको लगता है कि (जानबूझकर?) ने निपटान() कथन को गलत स्थान दिया है। – wodzu

+0

@ Paweł, आप सही हैं, वह कोड भी संकलित नहीं हुआ :) मुझे लगता है कि एक गलत संस्करण चिपकाया गया है, अब तय किया गया है। इसे तलाशने के लिए धन्यवाद। आप एक और सामान्य दृष्टिकोण की जांच कर सकते हैं: http://stackoverflow.com/a/22262976/1768303 – Noseratio

+0

मैंने इस कोड को चलाने की कोशिश की, हालांकि यह 'task.Wait(); 'पर अटक गया। मैं कुछ गलत कर रहा हूँ? – 0014

0

एक सरल समाधान है, जिस पर कई WebBrowsers के एक साथ संचालन होता है

  1. बनाएँ नए विंडोज फॉर्म्स आवेदन
  2. प्लेस बटन नामित Button1
  3. प्लेस पाठ बॉक्स textBox1 पाठ क्षेत्र की
  4. सेट गुण नामित: बहुपंक्ति सच्चे और स्क्रॉलबार दोनों
  5. लिखें निम्नलिखित बटन 1 हैंडलर पर क्लिक करें:

    textBox1.Clear(); 
    textBox1.AppendText(DateTime.Now.ToString() + Environment.NewLine); 
    int completed_count = 0; 
    int count = 10; 
    for (int i = 0; i < count; i++) 
    { 
        int tmp = i; 
        this.BeginInvoke(new Action(() => 
        { 
         var wb = new WebBrowser(); 
         wb.ScriptErrorsSuppressed = true; 
         wb.DocumentCompleted += (cur_sender, cur_e) => 
         { 
          var cur_wb = cur_sender as WebBrowser; 
          if (cur_wb.Url == cur_e.Url) 
          { 
           textBox1.AppendText("Task " + tmp + ", navigated to " + cur_e.Url + Environment.NewLine); 
           completed_count++; 
          } 
         }; 
         wb.Navigate("https://stackoverflow.com/questions/4269800/webbrowser-control-in-a-new-thread"); 
        } 
        )); 
    } 
    
    while (completed_count != count) 
    { 
        Application.DoEvents(); 
        Thread.Sleep(10); 
    } 
    textBox1.AppendText("All completed" + Environment.NewLine); 
    
संबंधित मुद्दे