C# 如何调用WebBrowser Navigate浏览多个URL?
要收集网页上的信息,我可以使用WebBrowser.Navigated事件 首先,导航到url:C# 如何调用WebBrowser Navigate浏览多个URL?,c#,winforms,webbrowser-control,webclient,async-await,C#,Winforms,Webbrowser Control,Webclient,Async Await,要收集网页上的信息,我可以使用WebBrowser.Navigated事件 首先,导航到url: WebBrowser wbCourseOverview = new WebBrowser(); wbCourseOverview.ScriptErrorsSuppressed = true; wbCourseOverview.Navigate(url); wbCourseOverview.Navigated += wbCourseOverview_Navigated; 然后在调用“导航”时处理网页
WebBrowser wbCourseOverview = new WebBrowser();
wbCourseOverview.ScriptErrorsSuppressed = true;
wbCourseOverview.Navigate(url);
wbCourseOverview.Navigated += wbCourseOverview_Navigated;
然后在调用“导航”时处理网页:
void wbCourseOverview_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
//Find the control and invoke "Click" event...
}
当我尝试遍历URL的字符串数组时,最困难的部分出现了
foreach (var u in courseUrls)
{
WebBrowser wbCourseOverview = new WebBrowser();
wbCourseOverview.ScriptErrorsSuppressed = true;
wbCourseOverview.Navigate(u);
wbCourseOverview.Navigated += wbCourseOverview_Navigated;
}
在这里,由于页面加载需要时间,因此永远不会到达wbCourseOverview\u Navigated
我尝试在C5中使用异步等待。任务和基于事件的异步模式EAP可在中找到。另一个例子可以在中找到
问题是WebClient具有类似DownloadDataAsync和DownloadStringAsync的异步方法。但WebBrowser中没有NavigateAsync
有专家能给我一些建议吗?多谢各位
StackOverflow中有一个帖子。但是,有人知道如何在答案中实现这一点吗
再次更新
在,
在我的web浏览器访问第二个url之前,它看起来不错
试图在任务已完成时将其转换为最终状态
我知道我一定是在foreach循环中出错了。因为DocumentCompleted事件在循环到第二轮时未引发。在foreach循环中写入此wait的正确方法是什么?不要使用wbCourseOverview\u导航使用webBrowser1\u 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++]);
}
不要使用wbCourseOverview\u导航,而是在第一次URL加载完成时使用webBrowser1\u DocumentCompleted并转到下一个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++]);
}
这里有一个邮局。但是,有人知道如何在答案中实现这一点吗
好的,那么您需要一些带有waiter的代码。我已经编写了两段代码。
第一个使用TPL的内置等待器:
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;
//}
下一个示例包含Eric Lippert提到的waiter结构的示例实现
希望这有帮助
这里有一个邮局。但是,有人知道如何在答案中实现这一点吗
好的,那么您需要一些带有waiter的代码。我已经编写了两段代码。
第一个使用TPL的内置等待器:
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;
//}
下一个示例包含Eric Lippert提到的waiter结构的示例实现
希望这有帮助。Ha!这个答案让我再次感到愚蠢。为什么我必须坚持我的foreach循环?!在标记答案之前,我会等待更多的答案,只是想看看是否有人提供了一些异步等待解决方案,因为我真的很想知道。但是谢谢你IRSOG的快速回复。@Blaise:WebBrowser类在.NET中的异步/等待实现有一个方法:检查一下,我已经在那篇文章中担任主角了。但是你知道如何实现这种支撑吗?我以前没有尝试过,但也看到了这一点:我尝试使用上一篇文章中提供的解决方案。但也有一些困难。请在原始帖子中查看我的更新。谢谢,哈!这个答案让我再次感到愚蠢。为什么我必须坚持我的foreach循环?!在标记答案之前,我会等待更多的答案,只是想看看是否有人提供了一些异步等待解决方案,因为我真的很想知道。但是谢谢你IRSOG的快速回复。@Blaise:WebBrowser类在.NET中的异步/等待实现有一个方法:检查一下,我已经在那篇文章中担任主角了。但是你知道如何实现这种支撑吗?我以前没有尝试过,但也看到了这一点:我尝试使用上一篇文章中提供的解决方案。但也有一些困难。请在原始帖子中查看我的更新。谢谢。你想从WebBrowser控件中删除HTML吗?如果是这样的话,这是一种非常低效的方法,因为加载所有图像、JavaScript和插件会带来大量开销。您可以自己处理HTTP请求,然后对响应进行处理。如果您阅读了链接到的文章,那么您应该能够使用Navigate、Navigated和TaskCompletionSource自己构建NavigateAsync。@CameronTinker,我需要的不仅仅是HTML。我想要的是在一些DOM控件上调用Click事件。所以我不会只使用DownloadStringTaskAsyc。@svick,我认为你指向了一个好的方向。这就是我想做的。你能给我更多的指示吗?为什么你建议我使用Navigated而不是DocumentCompleted来构建NavigateEasyc?@Blaise我建议使用Navigared只是因为你在原始代码中使用了Navigared。你是否试图从WebBrowser控件中删除HTML?如果是这样的话,这是一种非常低效的方法,因为加载所有图像、JavaScript和插件会带来大量开销。您可以自己处理HTTP请求,然后对响应进行处理。如果您阅读了链接到的文章,那么您应该能够使用Navigate、Navigated和TaskCompletionSource自己构建NavigateAsync。@CameronTinker,我需要的不仅仅是HTML。我想要的是调用Click事件o
n一些DOM控件。所以我不会只使用DownloadStringTaskAsyc。@svick,我认为你指向了一个好的方向。这就是我想做的。你能给我更多的指示吗?为什么你建议我使用Navigated而不是DocumentCompleted来构建NavigateEasyc?@Blaise我建议使用NavigateGared只是因为这是你在原始代码中使用的。谢谢你的帮助。在这个解决方案中,您似乎使用了wait或async关键字。你有什么理由避开他们吗?在这种情况下,它们不容易实现吗?这个答案非常详细。现在我至少有了一个有效的例子。谢谢你,谢谢你的帮助。在这个解决方案中,您似乎使用了wait或async关键字。你有什么理由避开他们吗?在这种情况下,它们不容易实现吗?这个答案非常详细。现在我至少有了一个有效的例子。非常感谢。
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);
}
});
}
}
}