WebBrowser是否有Application.DoEvents()? [英] is there an Application.DoEvents() for WebBrowser?

查看:155
本文介绍了WebBrowser是否有Application.DoEvents()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 定时器 ,以确定使用AJAX加载的页面是否准备就绪,并且只有在准备就绪时返回(包含ajax内容的页面加载)。我正在尝试像下面的代码,但我想出了一个 Application.DoEvents() 只处理挂起的Windows消息循环项,因此它会运行到无限循环,因为 Applicadion.DoEvents() 不会引发任何 WebBrowser 的事件(但只有Windows提供的一个),所以 ReadyState 不能更新,永远不会更改。 / p>

我的问题是:有没有办法强制 WebBrowser的事件 Application.DoEvents() 是吗?

  static bool done = false; 
int [] foo()
{
int [] data;
timer1.Interval = 1000;
timer1.Tick + = new EventHandler(delegate(object o,EventArgs ea)
{
if(browser.ReadyState == WebBrowserReadyState.Complete)
{
timer1 .Stop();
data = extract_data();
done = true;
}
});
timer1.Start();

while(!done)/ *从函数返回只有当timer1不再运行时* /
{
Application.DoEvents();
Thread.Sleep(1000);
}

返回数据;
}

我知道 Application.DoEvents() 问题,但我找不到任何其他方法。如果您使用的是.NET 4.5或更高版本(4.0如果您是...)愿意使用 Microsoft.Bcl.Async 库),这可以很容易地完成通过 TaskCompletionSource 等待

 异步任务< ; INT [] GT; foo()
{
//创建完成源和回调委托。
var tcs = new TaskCompletionSource< object>();
WebBrowserDocumentCompletedEventHandler callback =(sender,args)=> tcs.SetResult(NULL);

//订阅Document完成的事件并运行回调。
browser.DocumentCompleted + = callback;

try
{
//我们可能已经处于完整状态,所以事件永远不会触发。
//因此,如果我们处于完成状态,我们可以跳过等待。
if(browser.ReadyState!= WebBrowserReadyState.Complete)
{
//等待完成的事件触发。
await tcs.Task;
}
}
finally
{
//取消订阅nolonger所需的回调。
browser.DocumentCompleted - = callback;
}

//处理已完成文档中的数据。
var data = extract_data();
返回数据;
}

这段代码将会订阅 DocumentCompleted 事件然后可以等待文档完成,如果它还没有完成加载,而它等待它返回控制到调用者(与DoEvents循环相同的效果,但更好)一旦事件触发它处理数据并返回结果。但是,如果可能,一个更好的解决方案是重新编写你的代码,从来不会调用 foo 只需订阅 DocumentCompleted 事件,并将数据推送到需要的位置,而不是拉取。


I'm using a Timer to determine if a page loaded using AJAX is ready and return from function only when it is ready (page load including ajax stuff was loaded). I was trying the code like the below but I figured out Application.DoEvents() only processes pending Windows message loop items so it run into an infinity loop because Applicadion.DoEvents() doesn't raise any WebBrowser's events (but only Windows one as I mentioned) so ReadyState can't be update and never change.

My question is: Is there any way to force WebBrowser's events Application.DoEvents() does?

static bool done = false;
int[] foo()
{
  int[] data;
 timer1.Interval = 1000;
            timer1.Tick += new EventHandler(delegate(object o, EventArgs ea)
                {
                    if (browser.ReadyState == WebBrowserReadyState.Complete)
                    {
                        timer1.Stop();
                        data = extract_data();
                        done = true;
                    }
                });
            timer1.Start();

            while(!done) /* return from function only if timer1 isn't running anymore */
            {
                Application.DoEvents();
                Thread.Sleep(1000);
            }

            return data;
}

I'm aware about Application.DoEvents() "issues" but I can't find any other way to do that. An different approach to solve that is very welcome too.

解决方案

If you are using .NET 4.5 or newer (4.0 if you are willing to use the Microsoft.Bcl.Async library) this can be easily done via a TaskCompletionSource and an await

async Task<int[]> foo()
{
    //Create the completion source and the callback delegate.
    var tcs = new TaskCompletionSource<object>();
    WebBrowserDocumentCompletedEventHandler callback = (sender, args) => tcs.SetResult(null);

    //Subscribe to the Document completed event and run the callback.
    browser.DocumentCompleted += callback;

    try
    {
        //We may already be in the complete state so the event will never fire.
        //Therefor if we are in the completed state we can skip the await.
        if (browser.ReadyState != WebBrowserReadyState.Complete)
        {
            //Wait here for the completed event to fire.
            await tcs.Task;
        }
    }
    finally
    {
        //Unsubscribe the callback which is nolonger needed.
        browser.DocumentCompleted -= callback;
    }

    //Process the data from the completed document.
    var data = extract_data();
    return data;
}

What this code will do is subscribe to the DocumentCompleted event then will optionally wait for the document to finish if it has not finished loading yet, while it is waiting it returned control to the caller (the same effect as your DoEvents loop, but much better) once the event fires it processes the data and returns the result.

However, if possible, a even better solution is re-write your code to never call foo at all and just subscribe to the DocumentCompleted event and have that push the data to where it needs to go instead of pulling it.

这篇关于WebBrowser是否有Application.DoEvents()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆