繁体   English   中英

等待事件的Reactive Extensions第一次无法使用

[英]Reactive Extensions waiting for event doesn't work first time around

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

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

它们一起组成一对:当“ 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直到再次NavigatingDocumentCompleted触发(即,我转到另一个URL或相同的URL)。

我做了一个快速的项目,只是为了测试这一点,并且事件NavigatingDocumentCompleted如预期那样触发,这是我的完整代码:

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为:

  • 导航解雇
  • DocumentCompleted已解雇
  • ... ... 没有

如果然后在WebBrowser单击链接,例如在顶部说图片,则会发生以下情况:

  • 导航解雇
  • DocumentCompleted已解雇
  • 1秒后...完成加载

如果我再次按下Button ,那么会发生以下情况:

  • 导航解雇
  • DocumentCompleted已解雇
  • 1秒后...完成加载
  • 显然,如果我以前没有单击页面中的任何链接,那么我会得到第二个DoneLoading 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM