等待DocumentCompleted事件的WPF方法

时间:2011-09-06 17:46:59

标签: c# wpf browser

我知道这有been asked before,但我认为these solutions不灵活。 DocumentCompleted事件应该用于确定负载何时完成,而不是用于执行工作的方法。如果您需要执行几个不同的任务,每个任务必须多次导航,将逻辑放在DocumentCompleted事件中会将其变成一个难以阅读和维护的凌乱的交换机/案例路由器。

你需要在你的方法执行导航期间可以实际等待的东西,这样你就可以用你已经存在的方法继续你的任务。我的第一个是实际的Wait()方法。

我认为这样的事情很接近:

void WaitForLoad()
    {
        isLoading = true;
        while (isLoading)
        {
            if (Application.Current == null) break;
            Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, (DispatcherOperationCallback)delegate(object unused) { return null; }, null);
        }
    }

并在DocumentCompleted事件中将Isloading设置为false。

您应该能够在任何导致页面加载的操作之后调用此方法。它有效,它有一些问题。

1)它将应用程序的CPU使用率最多发送到35%,直到页面加载完毕,即使没有其他任何事情发生。

2)如果应用程序在其运行时尝试关闭,则循环将继续运行并且在没有窗口的情况下打开应用程序,因此当应用程序为空时需要中断。

这可以修复,还是我会以错误的方式来到这里?

编辑:我尝试在下面实施ManualResetEvent解决方案,但它导致了其他一些我不确定可以解决的问题,而不会造成比上面更糟糕的情况。由于WebBrowser在UI上,因此锁定线程会停止整个应用程序。如果工作在后台线程上完成,则可以锁定,但随后访问WebBrowser变得非常困难。

2 个答案:

答案 0 :(得分:2)

在您的情况下,听起来您希望在等待加载文档时阻止特定线程。在这种情况下,你会做这样的事情:

  protected ManualResetEvent _resetEvent = new ManualResetEvent(false);

  public void WaitingThread()
  {
      _resetEvent.WaitOne();

      // Do stuff after the web browser completes. 
  }

  public void LoadWebPage()
  {
      webBrowser.Navigate(new Uri(url));
      webBrowser.DocumentCompleted = (s, e) => { _resetEvent.Set(); };
  }

基本上,当文档完成时,您会发出事件信号,并且等待事件的所有线程都会解锁并继续执行。

答案 1 :(得分:0)

我注意到你使用Dispatcher.CurrentDispatcher.Invoke这对调用你的方法很有用,它以某种方式从另一个线程更新UI。但是从提供的代码中,我看不到其他线程中的任何代码然后是UI。所以

  1. 在另一个线程上运行该代码。

  2. 在应用程序的关闭事件中,您可以isLoading=false;等等,如果调用的方法是长期运行的东西插入

    如果(!isLoading)    返回;

    //或以其他适合的方式破解执行

  3. 编辑:

    更好的方法是在多线程中处理这个,然后只是简单地继续布尔变量,使用一些Synchonization object