等待 DocumentCompleted 事件的 WPF 方法

发布于 2024-12-03 14:32:38 字数 1308 浏览 0 评论 0原文

我知道之前已被问过< /a>,但我认为这些解决方案并不灵活。 DocumentCompleted 事件应用于确定加载何时完成,而不是作为执行工作的方法。如果您需要执行多个不同的任务,每个任务都必须导航多次,那么将逻辑放在 DocumentCompleted 事件中会将其变成一个难以阅读和维护的混乱的 switch/case 路由器。

您需要在方法执行导航期间实际等待的东西,以便您可以在已经所在的方法中继续执行任务。我的第一个方法是实际的 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 上,锁定线程会停止整个应用程序。如果工作是在后台线程上完成的,则可以将其锁定,但是访问 Web 浏览器会变得非常困难。

I know this has been asked before, but I don't think these solutions are flexible. The DocumentCompleted event should be used to determine when the load has completed, not as a method for performing work. If you need to perform several different tasks that each have to navigate several times, placing the logic in the DocumentCompleted event turns it into a messy switch/case router that is hard to read and maintain.

You need something that can actually wait during your method performing navigation so you can continue your task in the method you are already in. My first though is an actual Wait() method.

I would think something like this is close:

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

And set Isloading to false in the DocumentCompleted event.

You should be able to just call this method after whatever action will cause a pageload. It works, it has some issues.

1) it sends the CPU usage for the app up to 35% until the page has loaded, even if nothing else is happening.

2) if the application tries to close while its running, the loop will keep running and leave the app open with no windows, hence the need for the break when the app is null.

Can this be fixed, or am I coming at this all the wrong way?

Edit: I tried implementing the ManualResetEvent solution below, but it led to several other issues that I am not sure can be resolved without creating a messier situation than the one above. Since the WebBrowser is on the UI, locking the thread stop the entire app. If the work is done on the background thread it can be locked, but then accessing the WebBrowser becomes very difficult.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

苯莒 2024-12-10 14:32:38

在您的情况下,听起来您希望在等待文档加载时阻塞特定线程。在这种情况下,您将执行如下操作:

  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(); };
  }

基本上,当文档完成时,您向该事件发出信号,并且等待该事件的任何线程都会解除阻塞并继续执行。

In your situation, it sounds like you want a specific thread to block while waiting for the document to load. In that case, you would do something like this:

  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(); };
  }

Basically, when the document completes, you signal the event and any threads waiting on the event unblock and continue executing.

流年已逝 2024-12-10 14:32:38

我注意到您使用 Dispatcher.CurrentDispatcher.Invoke 这非常适合调用以某种方式从另一个线程更新 UI 的方法。但从提供的代码来看,我在 UI 之外的其他线程中没有看到任何代码。所以

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

  2. 在应用程序的关闭事件中,您可以设置 isLoading=false; 而且,如果调用的方法是长时间运行的内容,则插入

    if(!正在加载)
    返回;

    //或以其他应用程序合适的方式中断执行

编辑:

在多线程中处理此问题的更好方法,然后只需简单地中继布尔变量,就是使用一些同步对象

I noticed that you use Dispatcher.CurrentDispatcher.Invoke this is good for calling your method that somehow updates UI from another thread. But from code provided, I don't see any code in other thread then UI. So

  1. Run that code on another thread.

  2. On the close event of your application you can make isLoading=false; And more, if the method invoked is kind of long running stuff insert

    if(!isLoading)
    return;

    //or in some other app suitable way break an execution

EDIT:

Even better way to handle this in multithreading, then just simply relay on boolean variable, is using some Synchonization object

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文