0

Application.DoEvents()で解決できる問題に直面しています。問題は、WebBrowser が非同期的に URL にナビゲートすることを前提としていますが、そうではなく、Application.DoEvents() を使用するとそれが解決することです。これは、アプリケーションが他のイベントを処理し、イベントを配信しないために発生すると思います。ナビを正しく。

このメソッドについて少し読んだところ、このメソッドによってアプリケーションがすべての currents イベントを処理するようになることがわかりました。大砲を使ってアリを殺したので、今は少し心配です。

4

2 に答える 2

4

はい、 Application.DoEvents() はこの問題を解決します。核となる問題は、WebBrowser がその中核部分で高度にスレッド化されたコンポーネントであることです。その Navigate() メソッドを呼び出すことができ、コードをブロックすることなく処理を開始します。メソッドはすぐに戻ります。

ただし、問題は、ある時点で DocumentCompleted イベントを実行する必要があることです。これは、ブラウザ オブジェクトを作成したスレッドで実行されることが保証されています。それを行うのは難しいです。あなたのスレッドは何か他のことをしているかもしれません。ループに座って、ReadyState プロパティをテストするように。このループを中断してイベント ハンドラを実行するメカニズムはありません。

したがって、ReadyState プロパティが変更されず、DocumentCompleted イベントが発生しないことがわかります。これはデッドロックと呼ばれ、スレッド化されたコードの非常に一般的な呪いです。DoEvents の使用はバックドアであり、「メッセージ ループをポンピング」します。これにより、ブラウザがスレッドに割り込んでイベントを発生させることができます。これにより、ReadyState プロパティが更新され、ループから抜け出すことができます。

ただし、DoEvents には大きな問題があります。選択的ではなく、イベントの発生を許可するメッセージの処理に限定されません。また、プログラムをクラッシュさせる種類の他の通知もディスパッチします。ユーザーが遅い Web サイトにいらいらして、フォームを閉じるように。これにより、ブラウザ オブジェクトが破棄されますが、ループは停止しません。破棄されたブラウザーの ReadyState プロパティをテストしています。カブーム!

これを別の方法で行う必要があります。ループ内で UI スレッドをブロックまたはハングアップすることは決して合法ではありません。デッドロックが発生しやすくなります。実際、これはSTA スレッドに関する Microsoft のガイドラインによって禁止されています。回避策は簡単です。待機ループの後のコードを DocumentCompleted イベント ハンドラーに移動します。イベントが特定の Web ページの完了を通知するか、ユーザーが結果に興味を示さなくなったことを知るために、いくつかの状態変数をクラスに追加する必要がある場合があります。

于 2012-10-14T12:07:39.997 に答える
1

このApplication.Dovents()メソッドは、保留中のすべてのメッセージを処理します。それは原因となる可能性があります:

  1. 現在のコードブロックが終了する前に、コードブロックを2回入力します。(ボタンクリックでブラウザをナビゲートするとします。ユーザーがボタンをクリックし、コードがブラウザを待っている間にユーザーが再度クリックしたことを確認します。その場合Application.Doevents()、次の行に進む前にそのメソッドが処理されます。)

  2. 重要なコードを中断します。(時間のかかる方法があり、ユーザーが閉じるボタンをクリックしたと仮定します。フォームは表示されなくなりますが、コードは引き続き実行されます。実際の問題です。

  3. さらに多くの予期しない結果。

ただし、この方法を使用することが必要な場合があり、マルチスレッドで使用するのが難しいWebブラウザーのような簡単なソリューション(特に表示されている場合)を感じることがあります。この方法を使用する必要がある場合は、ユーザーやその他のもの(タイマー、ボタン、イベントなど)が何も中断しないようにする必要があります。詳細については、Application.DoEvents()の使用をご覧ください。

于 2012-10-14T11:35:20.063 に答える