C# 任务未完成第二次[间歇性问题]–;异步/等待

C# 任务未完成第二次[间歇性问题]–;异步/等待,c#,.net,winforms,webbrowser-control,async-await,C#,.net,Winforms,Webbrowser Control,Async Await,我有一个WebBrowser控件是Windows窗体项目。它浏览“MyTableTest.html”中所有可用的URL。此页面中有四个URL,webbrowser会逐一浏览每个URL。一旦它到达最后一个,它应该再次进入第一个。它在第一次迭代中运行良好,但在第二次迭代中不会转到URL。这是一个间歇性问题-在某些情况下有效 从日志上看,他等待的任务似乎没有完成。如何使它在第二次迭代中也能工作 注:MyTableTest.html如下所示 注:这是基于帖子 发行 代码 public partial c

我有一个
WebBrowser
控件是Windows窗体项目。它浏览“MyTableTest.html”中所有可用的URL。此页面中有四个URL,webbrowser会逐一浏览每个URL。一旦它到达最后一个,它应该再次进入第一个。它在第一次迭代中运行良好,但在第二次迭代中不会转到URL。这是一个间歇性问题-在某些情况下有效

从日志上看,他等待的任务似乎没有完成。如何使它在第二次迭代中也能工作

注:MyTableTest.html如下所示

注:这是基于帖子

发行

代码

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        this.Load += MainForm_Load;
    }

    List<string> visitedProducts = new List<string>();
    string nextNavigationUrl = String.Empty;

    // Form Load event handler
    async void MainForm_Load(object sender, EventArgs e)
    {
        // cancel the whole operation in 20 sec
        var cts = new CancellationTokenSource(20000);

        //urlStore.Add(@"C:\Samples_L\MyTableTest.html");
        nextNavigationUrl = GetHomoePageUrl();
        await NavigateInLoopAsync(cts.Token);
    }

    // navigate to each URL in a loop
    async Task NavigateInLoopAsync(CancellationToken ct)
    {

        bool isIterationComplete = false;

        while (!isIterationComplete)
        {

            string url = String.Empty;

            if (String.IsNullOrEmpty(nextNavigationUrl))
            {
                WriteLogFunction("Close");
                isIterationComplete = true;
            }
            else
            {
                url = nextNavigationUrl;
                ct.ThrowIfCancellationRequested();


                WriteLogFunction("Calling NavigateAsync");

                Action startNavigation = () => this.webBrowser1.Navigate(url);
                var html = await NavigateAsync(ct, startNavigation);


            }
        }
    }

    // asynchronous navigation
    async Task<string> NavigateAsync(CancellationToken ct, Action startNavigation)
    {
        var onloadTcs = new TaskCompletionSource<bool>();
        EventHandler onloadEventHandler = null;

        WriteLogFunction("Inside Function NavigateAsync");

        WebBrowserDocumentCompletedEventHandler documentCompletedHandler = delegate
        {
            // DocumentCompleted may be called several time for the same page,
            // if the page has frames
            if (onloadEventHandler != null)
                return;

            // so, observe DOM onload event to make sure the document is fully loaded
            onloadEventHandler = (s, e) =>
                onloadTcs.TrySetResult(true);
            this.webBrowser1.Document.Window.AttachEventHandler("onload", onloadEventHandler);
        };

        this.webBrowser1.DocumentCompleted += documentCompletedHandler;

        try
        {
            using (ct.Register(() => onloadTcs.TrySetCanceled(), useSynchronizationContext: true))
            {
                startNavigation();

                WriteLogFunction("Location 1");

                // wait for DOM onload event, throw if cancelled
                await onloadTcs.Task;

                //ISSUE: Not reaching this location at second time navigation
                WriteLogFunction("Location 2");
            }
        }
        finally
        {
            this.webBrowser1.DocumentCompleted -= documentCompletedHandler;
            if (onloadEventHandler != null)
                this.webBrowser1.Document.Window.DetachEventHandler("onload", onloadEventHandler);
        }

        WriteLogFunction("Place 3");

        // the page has fully loaded by now

        // optional: let the page run its dynamic AJAX code,
        // we might add another timeout for this loop
        do { await Task.Delay(500, ct); }
        while (this.webBrowser1.IsBusy);

        //Call Processing -- Added By Lijo
        ExerciseApp(this.webBrowser1, null);

        // return the page's HTML content
        return this.webBrowser1.Document.GetElementsByTagName("html")[0].OuterHtml;
    }

    private void ExerciseApp(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        WriteLogFunction("ExerciseApp");
        var wb = sender as WebBrowser;
        int catalogElementIterationCounter = 0;
        var elementsToConsider = wb.Document.All;
        string productUrl = String.Empty;
        bool isClicked = false;

        foreach (HtmlElement e1 in elementsToConsider)
        {

            catalogElementIterationCounter++;

            string x = e1.TagName;
            String idStr = e1.GetAttribute("id");

            if (!String.IsNullOrWhiteSpace(idStr))
            {
                //Each Product Navigation
                if (idStr.Contains("catalogEntry_img"))
                {
                    productUrl = e1.GetAttribute("href");
                    if (!visitedProducts.Contains(productUrl))
                    {
                        WriteLogFunction("productUrl -- " + productUrl);
                        visitedProducts.Add(productUrl);
                        isClicked = true;

                        //e1.InvokeMember("Click");
                        nextNavigationUrl = productUrl;

                        break;
                    }

                }
            }
        }

        WriteLogFunction(visitedProducts.Count.ToString());
        WriteLogFunction(nextNavigationUrl);

        if (visitedProducts.Count == 4)
        {
            WriteLogFunction("Condition B");
            visitedProducts = new List<string>();
        }

        if (!isClicked)
        {
            WriteLogFunction("Condition C");
            nextNavigationUrl = GetHomoePageUrl();
        }
    }

    private void HomoePageNavigate()
    {
        webBrowser1.Navigate(GetHomoePageUrl());
    }

    private string GetHomoePageUrl()
    {
       return @"C:\Samples_L\MyTableTest.html";
    }

    private void WriteLogFunction(string strMessage)
    {
        using (StreamWriter w = File.AppendText("log.txt"))
        {
            w.WriteLine("\r\n{0} ..... {1} ", DateTime.Now.ToLongTimeString(), strMessage);
        }
    }



}
公共部分类表单1:表单
{
公共表格1()
{
初始化组件();
此.Load+=MainForm_Load;
}
列出已访问的产品=新列表();
string nextNavigationUrl=string.Empty;
//表单加载事件处理程序
异步void MainForm_加载(对象发送方,事件参数e)
{
//在20秒内取消整个操作
var cts=新的CancellationTokenSource(20000);
//添加(@“C:\Samples\u L\MyTableTest.html”);
nextNavigationUrl=GetHomoePageUrl();
等待NavigateInLopAsync(cts.Token);
}
//导航到循环中的每个URL
异步任务导航InLopAsync(取消令牌ct)
{
布尔isIterationComplete=假;
而(!isIterationComplete)
{
stringurl=string.Empty;
if(String.IsNullOrEmpty(nextNavigationUrl))
{
写功能(“关闭”);
isIterationComplete=true;
}
其他的
{
url=nextNavigationUrl;
ct.ThrowIfCancellationRequested();
WriteLogFunction(“调用NavigateAsync”);
Action startNavigation=()=>this.webBrowser1.Navigate(url);
var html=等待导航同步(ct、startNavigation);
}
}
}
//异步导航
异步任务NavigateAsync(取消令牌ct,操作开始导航)
{
var onload tcs=new TaskCompletionSource();
EventHandler onloadEventHandler=null;
WriteLogFunction(“内部函数NavigateAsync”);
WebBrowserDocumentCompletedEventHandler documentCompletedHandler=委托
{
//对于同一页,DocumentCompleted可以多次调用,
//如果页面有框架
if(onloadEventHandler!=null)
返回;
//因此,观察DOM onload事件以确保文档已完全加载
onloadEventHandler=(s,e)=>
onload tcs.TrySetResult(真);
this.webBrowser1.Document.Window.AttachEventHandler(“onload”,onloadEventHandler);
};
this.webBrowser1.DocumentCompleted+=documentCompletedHandler;
尝试
{
使用(ct.Register(()=>onload tcs.trysetconceled(),useSynchronizationContext:true))
{
startNavigation();
WriteLogFunction(“位置1”);
//等待DOM onload事件,如果取消则抛出
等待onload任务;
//问题:第二次导航时未到达此位置
WriteLogFunction(“位置2”);
}
}
最后
{
this.webBrowser1.DocumentCompleted-=documentCompletedHandler;
if(onloadEventHandler!=null)
this.webBrowser1.Document.Window.DetachEventHandler(“onload”,onloadEventHandler);
}
写功能(“第3处”);
//现在页面已完全加载
//可选:让页面运行其动态AJAX代码,
//我们可能会为此循环添加另一个超时
不要{等待任务。延迟(500,ct);}
而(这个.webBrowser1.IsBusy);
//呼叫处理——由Lijo添加
ExerciseApp(this.webBrowser1,null);
//返回页面的HTML内容
返回此.webBrowser1.Document.GetElementsByTagName(“html”)[0].OuterHtml;
}
私有void ExerciseApp(对象发送方,WebBrowserDocumentCompletedEventArgs e)
{
WriteLogFunction(“ExerciseApp”);
var wb=作为网络浏览器的发送方;
int catalogElementIterationCounter=0;
var elementstoconsive=wb.Document.All;
string productUrl=string.Empty;
bool isClicked=false;
foreach(元素中的HtmlElement e1考虑)
{
catalogElementIterationCounter++;
字符串x=e1.TagName;
字符串idStr=e1.GetAttribute(“id”);
如果(!String.IsNullOrWhiteSpace(idStr))
{
//每个产品导航
if(idStr.Contains(“目录条目”\u img))
{
productUrl=e1.GetAttribute(“href”);
如果(!visitedProducts.Contains(productUrl))
{
WriteLogFunction(“productUrl--”+productUrl);
visitedProducts.Add(productUrl);
isClicked=true;
//e1.调用成员(“单击”);
nextNavigationUrl=产品URL;
打破
}
}
}
}
WriteLogFunction(visitedProducts.Count.ToString());
WriteLogFunction(nextNavigationUrl);
if(visitedProducts.Count==4)
{
写函数(“条件B”);
visitedProducts=新列表();
}
如果(!isClicked)
{
写函数(“条件C”);
nextNavigationUrl=GetHomoePageUrl();
}
}
私有空白匀浆()
{
webBrowser1.Navigate(GetHomoePageUrl());
}
普里夫
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        this.Load += MainForm_Load;
    }

    List<string> visitedProducts = new List<string>();
    string nextNavigationUrl = String.Empty;

    // Form Load event handler
    async void MainForm_Load(object sender, EventArgs e)
    {
        // cancel the whole operation in 20 sec
        var cts = new CancellationTokenSource(20000);

        //urlStore.Add(@"C:\Samples_L\MyTableTest.html");
        nextNavigationUrl = GetHomoePageUrl();
        await NavigateInLoopAsync(cts.Token);
    }

    // navigate to each URL in a loop
    async Task NavigateInLoopAsync(CancellationToken ct)
    {

        bool isIterationComplete = false;

        while (!isIterationComplete)
        {

            string url = String.Empty;

            if (String.IsNullOrEmpty(nextNavigationUrl))
            {
                WriteLogFunction("Close");
                isIterationComplete = true;
            }
            else
            {
                url = nextNavigationUrl;
                ct.ThrowIfCancellationRequested();


                WriteLogFunction("Calling NavigateAsync");

                Action startNavigation = () => this.webBrowser1.Navigate(url);
                var html = await NavigateAsync(ct, startNavigation);


            }
        }
    }

    // asynchronous navigation
    async Task<string> NavigateAsync(CancellationToken ct, Action startNavigation)
    {
        var onloadTcs = new TaskCompletionSource<bool>();
        EventHandler onloadEventHandler = null;

        WriteLogFunction("Inside Function NavigateAsync");

        WebBrowserDocumentCompletedEventHandler documentCompletedHandler = delegate
        {
            // DocumentCompleted may be called several time for the same page,
            // if the page has frames
            if (onloadEventHandler != null)
                return;

            // so, observe DOM onload event to make sure the document is fully loaded
            onloadEventHandler = (s, e) =>
                onloadTcs.TrySetResult(true);
            this.webBrowser1.Document.Window.AttachEventHandler("onload", onloadEventHandler);
        };

        this.webBrowser1.DocumentCompleted += documentCompletedHandler;

        try
        {
            using (ct.Register(() => onloadTcs.TrySetCanceled(), useSynchronizationContext: true))
            {
                startNavigation();

                WriteLogFunction("Location 1");

                // wait for DOM onload event, throw if cancelled
                await onloadTcs.Task;

                //ISSUE: Not reaching this location at second time navigation
                WriteLogFunction("Location 2");
            }
        }
        finally
        {
            this.webBrowser1.DocumentCompleted -= documentCompletedHandler;
            if (onloadEventHandler != null)
                this.webBrowser1.Document.Window.DetachEventHandler("onload", onloadEventHandler);
        }

        WriteLogFunction("Place 3");

        // the page has fully loaded by now

        // optional: let the page run its dynamic AJAX code,
        // we might add another timeout for this loop
        do { await Task.Delay(500, ct); }
        while (this.webBrowser1.IsBusy);

        //Call Processing -- Added By Lijo
        ExerciseApp(this.webBrowser1, null);

        // return the page's HTML content
        return this.webBrowser1.Document.GetElementsByTagName("html")[0].OuterHtml;
    }

    private void ExerciseApp(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        WriteLogFunction("ExerciseApp");
        var wb = sender as WebBrowser;
        int catalogElementIterationCounter = 0;
        var elementsToConsider = wb.Document.All;
        string productUrl = String.Empty;
        bool isClicked = false;

        foreach (HtmlElement e1 in elementsToConsider)
        {

            catalogElementIterationCounter++;

            string x = e1.TagName;
            String idStr = e1.GetAttribute("id");

            if (!String.IsNullOrWhiteSpace(idStr))
            {
                //Each Product Navigation
                if (idStr.Contains("catalogEntry_img"))
                {
                    productUrl = e1.GetAttribute("href");
                    if (!visitedProducts.Contains(productUrl))
                    {
                        WriteLogFunction("productUrl -- " + productUrl);
                        visitedProducts.Add(productUrl);
                        isClicked = true;

                        //e1.InvokeMember("Click");
                        nextNavigationUrl = productUrl;

                        break;
                    }

                }
            }
        }

        WriteLogFunction(visitedProducts.Count.ToString());
        WriteLogFunction(nextNavigationUrl);

        if (visitedProducts.Count == 4)
        {
            WriteLogFunction("Condition B");
            visitedProducts = new List<string>();
        }

        if (!isClicked)
        {
            WriteLogFunction("Condition C");
            nextNavigationUrl = GetHomoePageUrl();
        }
    }

    private void HomoePageNavigate()
    {
        webBrowser1.Navigate(GetHomoePageUrl());
    }

    private string GetHomoePageUrl()
    {
       return @"C:\Samples_L\MyTableTest.html";
    }

    private void WriteLogFunction(string strMessage)
    {
        using (StreamWriter w = File.AppendText("log.txt"))
        {
            w.WriteLine("\r\n{0} ..... {1} ", DateTime.Now.ToLongTimeString(), strMessage);
        }
    }



}
<html>
<head>

    <style type="text/css">
        table {
            border: 2px solid blue;
        }

        td {
            border: 1px solid teal;
        }
    </style>

</head>
<body>

    <table id="four-grid">
         <tr>
            <td>
                <a href="https://www.wikipedia.org/" id="catalogEntry_img63666">

                    <img src="ssss"
                        alt="B" width="70" />
                </a>
            </td>
            <td>
                <a href="http://www.keralatourism.org/" id="catalogEntry_img63667">

                    <img src="ssss"
                        alt="A" width="70" />
                </a>
            </td>
        </tr>
        <tr>
            <td>
                <a href="https://stackoverflow.com/users/696627/lijo" id="catalogEntry_img63664">

                    <img src="ssss"
                        alt="G" width="70" />
                </a>
            </td>
            <td>
                <a href="http://msdn.microsoft.com/en-US/#fbid=zgGLygxrE84" id="catalogEntry_img63665">

                    <img src="ssss"
                        alt="Y" width="70" />
                </a>
            </td>
        </tr>

    </table>
</body>

</html>
onloadEventHandler = (s, e) => { Log("inside onloadEventHandler");
    onloadTcs.TrySetResult(true); }