等待事件的Reactive Extensions第一次无效

时间:2016-03-31 09:25:33

标签: c# .net system.reactive

我正在尝试使用WebBrowser控件创建一个方法,导航到网页并阻止执行,直到页面完全加载。

不幸的是,知道页面是否已完全加载并不是那么简单,只是基于事件NavigatingDocumentCompleted

他们一起成对:当Navigating开火时,DocumentCompleted将会在此之后开火。

不幸的是DocumentCompleted会为已加载的每一帧触发,因此每页可能会多次触发,这意味着看到以下序列并不罕见:Navigating - DocumentCompleted - {{ 1}} - Navigating

因此,我已将“页面已满载”定义如下:如果DocumentCompleted已经触发,并且在此期间没有DocumentCompleted再次触发,则已经过了一秒钟。

无论如何,我已经将以下内容作为我的Rx代码来尝试执行上述操作:

Navigating

然后在其他地方我做_pageLoaded = navigating.Select(_ => documentCompleted.Delay(TimeSpan.FromSeconds(1))).Switch().FirstAsync(); 才继续。

然而,由于一些奇怪的原因,这在第一次不起作用。因此,当应用程序加载并且await _pageLoaded在某处导航时,它会卡在WebBrowser上,直到await _pageLoadedNavigating再次触发(即,我转到另一个网址 - 或同一个)。

我做了一个快速项目,只是为了对此进行测试,事件DocumentCompletedNavigating按预期启动,这是我的完整代码:

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"); } } (我使用google.com测试过)中输入网址并点击TextBox时的结果是:

  • 导航解雇
  • DocumentCompleted已解雇
  • ...... ......没什么

如果然后在Button点击链接,例如在顶部说图像,则会发生以下情况:

  • 导航解雇
  • DocumentCompleted已解雇
  • 1秒后...... DoneLoading

如果我再次点击WebBrowser,则会发生以下情况:

  • 导航解雇
  • DocumentCompleted已解雇
  • 1秒后...... DoneLoading
  • 很明显,如果我之前没有点击页面中的任何链接,那么我会得到第二个DoneLoading Button

所以,我的问题很简单:第一次它无法正常工作,我该如何解决?

编辑:我刚刚在一个不同的网站上进行了测试,其中的事件多次触发,并且在这些网站上运行正常。所以它实际上只是一次点火的网站,而且它似乎只是第一次出现问题。

1 个答案:

答案 0 :(得分:4)

问题是你在之后等待你已经调用了Navigate - 所以根据是否同步引发Navigate事件,Rx从未看到第一个导航事件或者它是一个竞赛

试试这个:

    private async void button1_Click_1(object sender, EventArgs e)
    {
        var waiter = _pageLoaded.GetAwaiter();
        webBrowser.Navigate(textBox1.Text);
        await waiter;
        MessageBox.Show("DoneLoading");
    }

顺便说一下,正因为如此,它在异步代码中的一个非常常见的模式是开始等待事件完成而然后启动它 - 所以这是一个值得记住的好事。