2016-03-31 9 views
1

WebBrowserコントロールを使用して、Webページに移動し、ページが完全にロードされるまで実行をブロックするメソッドを作成しようとしています。イベントを待っているアクティブな拡張機能が初めて動作しない

残念ながら、ページが完全に読み込まれたかどうかは、単純ではなく、単にイベントNavigatingDocumentCompletedに基づいています。

これらは一緒にペアになります。Navigatingが発生すると、DocumentCompletedはそれ以降常に起動します。 DocumentCompletedからDocumentCompleted - - NavigatingNavigating:それは、次の手順を見て珍しいことではありませんつまり、ページごとに複数回発射することができるように、ロードされたフレーム毎に

残念ながらDocumentCompleted火災。

結果として、私は次のように「ページ、完全にロードされた」定義しました:DocumentCompletedは解雇しており、第二はNavigatingがその時間の間に再び発射せずに経過した場合。

とにかく、私は上記を実行しようとする私のRxのコードとして以下を持っている:

_pageLoaded = navigating.Select(_ => documentCompleted.Delay(TimeSpan.FromSeconds(1))).Switch().FirstAsync(); 

次にどこかに私は続行する前await _pageLoadedを行います。

しかし、いくつかの奇妙な理由で、これは初めて動作しません。したがって、アプリケーションが読み込まれ、WebBrowserがどこかをナビゲートすると、NavigatingDocumentCompletedの両方が再び発生するまで(つまり別のURLに移動するか、同じURLに移動する)、await _pageLoadedでスタックされます。

私はこれをテストするために迅速なプロジェクトと期待通りのイベント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をヒットした場合

をDoneLoading何が起こるかは、その後です:

  • ナビゲーションは
  • DocumentCompletedは後で
  • 1秒を解雇解雇しました...DoneLoading
  • そして明らかに私が前にページ内のリンクをクリックしなかったなら、2番目のDoneLoadingを取得しますMessageBox

私の質問は簡単です。最初はうまくいかず、どうすれば修正できますか?

EDIT:イベントが複数回発生する別のウェブサイトでテストしたところ、これらのウェブサイトで問題なく動作しました。だから、それは文字通り一度だけ発生するウェブサイトであり、それは最初の周りの問題であるように見えます。

答えて

4

の後にNavigateイベントが同期的に発生するかどうかに応じて、Rxは最初のnavigateイベントを見ないか、レースです。

これを試してみてください:

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

ところで、まさにこの理由のために非同期コードでその非常に一般的なパターンは、イベントの完了を待って起動すると、その後は、それを開始 - これはに良いものです覚えている。

+1

これはまさに問題でした。これはObservablesをイベントとして考え、 'Observable = Observable.FromEventPattern(webBrowser、" Navigating ");を実行することで、それによって生成されたイベントに私をサブスクライブし、私が欲しいときはいつでも、私が欲しがっていたものを拾った。今私はよく知っている;)ありがとう! – JohnUbuntu

+0

この回答も役に立ちます:http://stackoverflow.com/questions/19895373/how-to-use-observable-fromevent-instead-of-fromeventpattern-and-avoid-string-lit/19896246#19896246 –

関連する問題