[英]How to call WebBrowser Navigate to go through a number of urls?
要收集網頁上的信息,我可以使用WebBrowser.Navigated
事件。
首先,導航到網址:
WebBrowser wbCourseOverview = new WebBrowser();
wbCourseOverview.ScriptErrorsSuppressed = true;
wbCourseOverview.Navigate(url);
wbCourseOverview.Navigated += wbCourseOverview_Navigated;
然后在調用Navigated
時處理網頁:
void wbCourseOverview_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
//Find the control and invoke "Click" event...
}
當我嘗試通過字符串數組的網址時,困難的部分來了。
foreach (var u in courseUrls)
{
WebBrowser wbCourseOverview = new WebBrowser();
wbCourseOverview.ScriptErrorsSuppressed = true;
wbCourseOverview.Navigate(u);
wbCourseOverview.Navigated += wbCourseOverview_Navigated;
}
在這里,因為頁面加載需要時間, wbCourseOverview_Navigated
永遠不會達到wbCourseOverview_Navigated
。
我試圖在C#5中使用async
await
。 任務和基於事件的異步模式(EAP)可在此處找到。 另一個例子可以在基於任務的異步模式中找到 。
問題是WebClient
有像DownloadDataAsync
和DownloadStringAsync
這樣的異步方法。 但是WebBrowser
沒有NavigateAsync
。
有專家可以給我一些建議嗎? 謝謝。
StackOverflow中有一篇文章( 這里 )。 但是,有誰知道如何在答案中實現這個strut
?
再次更新。
public static Task WhenDocumentCompleted(this WebBrowser browser)
{
var tcs = new TaskCompletionSource<bool>();
browser.DocumentCompleted += (s, args) => tcs.SetResult(true);
return tcs.Task;
}
所以我有:
foreach (var c in courseBriefs)
{
wbCourseOverview.Navigate(c.Url);
await wbCourseOverview.WhenDocumentCompleted();
}
它看起來不錯,直到我的網絡瀏覽器訪問第二個網址。
嘗試將任務轉換為已完成的最終狀態。
我知道我必須在foreach
循環中犯了一個錯誤。 因為在循環到第二輪時沒有引發DocumentCompleted
事件。 在foreach
循環中寫這個await
的正確方法是什么?
StackOverflow中有一篇文章(這里)。 但是,有誰知道如何在答案中實現這個支柱?
好的,所以你想要一些代碼與awaiter。 我做了兩段代碼。 第一個使用TPL的內置awaiter:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ProcessUrlsAsync(new[] { "http://google.com", "http://microsoft.com", "http://yahoo.com" })
.Start();
}
private Task ProcessUrlsAsync(string[] urls)
{
return new Task(() =>
{
foreach (string url in urls)
{
TaskAwaiter<string> awaiter = ProcessUrlAsync(url);
// or the next line, in case we use method *
// TaskAwaiter<string> awaiter = ProcessUrlAsync(url).GetAwaiter();
string result = awaiter.GetResult();
MessageBox.Show(result);
}
});
}
// Awaiter inside
private TaskAwaiter<string> ProcessUrlAsync(string url)
{
TaskCompletionSource<string> taskCompletionSource = new TaskCompletionSource<string>();
var handler = new WebBrowserDocumentCompletedEventHandler((s, e) =>
{
// TODO: put custom processing of document right here
taskCompletionSource.SetResult(e.Url + ": " + webBrowser1.Document.Title);
});
webBrowser1.DocumentCompleted += handler;
taskCompletionSource.Task.ContinueWith(s => { webBrowser1.DocumentCompleted -= handler; });
webBrowser1.Navigate(url);
return taskCompletionSource.Task.GetAwaiter();
}
// (*) Task<string> instead of Awaiter
//private Task<string> ProcessUrlAsync(string url)
//{
// TaskCompletionSource<string> taskCompletionSource = new TaskCompletionSource<string>();
// var handler = new WebBrowserDocumentCompletedEventHandler((s, e) =>
// {
// taskCompletionSource.SetResult(e.Url + ": " + webBrowser1.Document.Title);
// });
// webBrowser1.DocumentCompleted += handler;
// taskCompletionSource.Task.ContinueWith(s => { webBrowser1.DocumentCompleted -= handler; });
// webBrowser1.Navigate(url);
// return taskCompletionSource.Task;
//}
而接下來的樣品中含有awaiter結構埃里克利珀的樣本實現在談論這里 。
public partial class Form1 : Form
{
public struct WebBrowserAwaiter
{
private readonly WebBrowser _webBrowser;
private readonly string _url;
private readonly TaskAwaiter<string> _innerAwaiter;
public bool IsCompleted
{
get
{
return _innerAwaiter.IsCompleted;
}
}
public WebBrowserAwaiter(WebBrowser webBrowser, string url)
{
_url = url;
_webBrowser = webBrowser;
_innerAwaiter = ProcessUrlAwaitable(_webBrowser, url);
}
public string GetResult()
{
return _innerAwaiter.GetResult();
}
public void OnCompleted(Action continuation)
{
_innerAwaiter.OnCompleted(continuation);
}
private TaskAwaiter<string> ProcessUrlAwaitable(WebBrowser webBrowser, string url)
{
TaskCompletionSource<string> taskCompletionSource = new TaskCompletionSource<string>();
var handler = new WebBrowserDocumentCompletedEventHandler((s, e) =>
{
// TODO: put custom processing of document here
taskCompletionSource.SetResult(e.Url + ": " + webBrowser.Document.Title);
});
webBrowser.DocumentCompleted += handler;
taskCompletionSource.Task.ContinueWith(s => { webBrowser.DocumentCompleted -= handler; });
webBrowser.Navigate(url);
return taskCompletionSource.Task.GetAwaiter();
}
}
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ProcessUrlsAsync(new[] { "http://google.com", "http://microsoft.com", "http://yahoo.com" })
.Start();
}
private Task ProcessUrlsAsync(string[] urls)
{
return new Task(() =>
{
foreach (string url in urls)
{
var awaiter = new WebBrowserAwaiter(webBrowser1, url);
string result = awaiter.GetResult();
MessageBox.Show(result);
}
});
}
}
}
希望這可以幫助。
而不是使用wbCourseOverview_Navigated
使用webBrowser1_DocumentCompleted
當第一次URL加載完成你的工作並轉到下一個url
List<string> urls = new List<string>();
int count = 0;
public Form1()
{
InitializeComponent();
webBrowser1.DocumentCompleted+=new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
}
private void Form1_Load(object sender, EventArgs e)
{
webBrowser1.Navigate(urls[count++]);
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//Do something
webBrowser1.Navigate(urls[count++]);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.