[英]Reactive Extensions waiting for event doesn't work first time around
我正在尝试创建一种方法,以使用WebBrowser
控件导航到网页并阻止执行,直到页面完全加载为止。
不幸的是,仅基于事件Navigating
和DocumentCompleted
知道页面是否已完全加载并不是那么简单。
它们一起组成一对:当“ Navigating
触发时, DocumentCompleted
将始终在此之后触发。
不幸的是, DocumentCompleted
会为已加载的每一帧触发,因此每页可能触发多次,这意味着看到以下顺序并不稀奇: Navigating
- DocumentCompleted
- Navigating
- DocumentCompleted
。
结果,我将“页面已完全加载”定义为以下内容:如果DocumentCompleted
已被触发并且已经过一秒钟而在此期间没有Navigating
再次触发。
无论如何,我将以下代码作为我的Rx代码来尝试执行上述操作:
_pageLoaded = navigating.Select(_ => documentCompleted.Delay(TimeSpan.FromSeconds(1))).Switch().FirstAsync();
然后在其他地方我先await _pageLoaded
然后再继续。
但是,出于某些奇怪的原因,这在第一时间不起作用。 因此,当应用程序加载并且WebBrowser
导航到某处时,它将卡在await _pageLoaded
直到再次Navigating
和DocumentCompleted
触发(即,我转到另一个URL或相同的URL)。
我做了一个快速的项目,只是为了测试这一点,并且事件Navigating
和DocumentCompleted
如预期那样触发,这是我的完整代码:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private IObservable<object> _pageLoaded;
private void Form1_Load(object sender, EventArgs e)
{
var navigating = Observable.FromEventPattern(webBrowser, "Navigating");
var documentCompleted = Observable.FromEventPattern(webBrowser, "DocumentCompleted");
_pageLoaded = navigating.Select(_ => documentCompleted.Delay(TimeSpan.FromSeconds(1))).Switch().FirstAsync();
}
private async void button1_Click(object sender, EventArgs e)
{
webBrowser.Navigate(textBox1.Text);
await _pageLoaded;
MessageBox.Show("DoneLoading");
}
private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
MessageBox.Show("DocumentCompleted fired");
}
private void webBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
MessageBox.Show("Navigating fired");
}
}
当有人在TextBox
输入一个URL(我用google.com测试过)并点击Button
为:
如果然后在WebBrowser
单击链接,例如在顶部说图片,则会发生以下情况:
如果我再次按下Button
,那么会发生以下情况:
MessageBox
。 因此,我的问题很简单:第一次无法解决什么问题,如何解决?
编辑 :我只是对另一个网站进行了测试,该网站多次触发该事件,并且在这些网站上都可以正常工作。 因此,从字面上看,它只触发一次,似乎只是第一次出现问题。
问题在于,您在调用“导航” 之后正在等待-因此,根据是否同步引发“导航”事件,Rx永远不会看到第一个导航事件,或者它是一场比赛。
尝试这个:
private async void button1_Click_1(object sender, EventArgs e)
{
var waiter = _pageLoaded.GetAwaiter();
webBrowser.Navigate(textBox1.Text);
await waiter;
MessageBox.Show("DoneLoading");
}
顺便说一句,由于这个原因,它是异步代码中非常常见的模式,它开始等待事件完成然后再启动它-因此这是一个值得记住的好方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.