如何避免循环中断?

Posted

技术标签:

【中文标题】如何避免循环中断?【英文标题】:How to avoid break in a loop? 【发布时间】:2014-03-26 15:31:48 【问题描述】:

我在 Windows 窗体项目中有一个 WebBrowser。它导航表格元素中的所有链接。它工作正常;但是它在循环中使用break。没有break声明如何实现这个功能?

注意:在我的真实场景中,如果我们使用该链接发出导航命令,所有链接都将重定向到登录页面。因此,在我的实际场景中,存储所有 url 并在之后进行导航对我不起作用。

C# 代码

public partial class Form1 : Form


string websiteUrl = @"C:\Samples_L\MyTableTest.html";
List<string> visitedUrls = new List<string>();
string currentUrl = String.Empty;

private void ExerciseApp(object sender, EventArgs e)


    Thread.Sleep(1000);

    if (currentUrl != websiteUrl)
    
        currentUrl = websiteUrl;
        wb.Navigate(websiteUrl);
    


    HtmlElement tableElement = wb.Document.GetElementById("four-grid");
    if (tableElement != null)
    
        foreach (HtmlElement e1 in tableElement.All)
        
            string x = e1.TagName;
            String idStr = e1.GetAttribute("id");

            if (!String.IsNullOrWhiteSpace(idStr))
            
                if (idStr.Contains("catalogEntry_img"))
                
                    string url = e1.GetAttribute("href");
                    if (!visitedUrls.Contains(url))
                    
                        currentUrl = url;
                        visitedUrls.Add(url);
                        e1.InvokeMember("Click");

                        //Use break when the first match is found
                        break;
                    
                
            
        
    





private System.Windows.Forms.WebBrowser wb = null;
private Button button1 = null;
private ListBox listBox1 = null;

public Form1()


    // button1
    button1 = new Button();
    button1.Location = new Point(20, 430);
    button1.Size = new Size(90, 23);
    button1.Text = "Load and Test";
    button1.Click += new EventHandler(this.button1_Click);

    // listBox1
    listBox1 = new ListBox();
    listBox1.Location = new Point(10, 460);
    listBox1.Size = new Size(460, 200);

    // Web Browser
    wb = new WebBrowser();
    wb.Location = new Point(10, 10);
    wb.Size = new Size(1000, 400);

    //Subscribing for the Document Completed Event
    wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(ExerciseApp);

    // Form1
    this.Text = "Web Browser Test";
    this.Size = new Size(5000, 7100);
    this.Controls.Add(wb);
    this.Controls.Add(button1);
    this.Controls.Add(listBox1);

    currentUrl = websiteUrl;


private void button1_Click(object sender, EventArgs e)

    listBox1.Items.Add("Loading Web app under test into WebBrowser control");
    wb.Url = new Uri(websiteUrl);





使用的 HTML

<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://***.com/users/696627/lijo" id="catalogEntry_img63664" class="itemhover"
                    onfocus="showPopupButton('category_63664');"
                    onkeydown="shiftTabHidePopupButton('category_63664',event);">

                    <img src="ssss"
                          />
                </a>
            </td>
            <td>
                <a href="http://msdn.microsoft.com/en-US/#fbid=zgGLygxrE84" id="catalogEntry_img63665" class="itemhover"
                    onfocus="showPopupButton('category_63665');"
                    onkeydown="shiftTabHidePopupButton('category_63665',event);">

                    <img src="ssss"
                          />
                </a>
            </td>
        </tr>
        <tr>
            <td>
                <a href="https://www.wikipedia.org/" id="catalogEntry_img63666" class="itemhover"
                    onfocus="showPopupButton('category_63666');"
                    onkeydown="shiftTabHidePopupButton('category_63666',event);">

                    <img src="ssss"
                          />
                </a>
            </td>
            <td>
                <a href="http://www.keralatourism.org/" id="catalogEntry_img63667" class="itemhover"
                    onfocus="showPopupButton('category_63667');"
                    onkeydown="shiftTabHidePopupButton('category_63667',event);">

                    <img src="ssss"
                          />
                </a>
            </td>
        </tr>
    </table>
</body>

</html>

参考

    Next using LINQ approach

【问题讨论】:

为什么要去掉break语句? 迭代自己而不是使用foreach,并在必须中断时保留一个等于true的布尔变量。在循环条件中,检查你有更多的元素,并且这个 bool 变量仍然是 false 参考Is it a bad practice to use break in a for loop? @Lijo 您的示例只有一个可以响应 break 的构造,因此我认为不需要基于删除它进行重构,但是,@Servy 的回答显示了重构的另一个原因:可读性和意图表达。 @CraigW。也许参考的是关于多个嵌套子块或代码长度的部分。 【参考方案1】:

您可以将其重构为查询,使代码的意图更加清晰:

var nextElement = tableElement.All
    .Where(element => element.GetAttribute("id") != null &&
        element.GetAttribute("id").Contains("catalogEntry_img") &&
        !visitedUrls.Contains(element.GetAttribute("href")))
    .FirstOrDefault();

if(nextElement != null)

    visitedUrls.Add(nextElement.GetAttribute("href"));
    nextElement.InvokeMember("Click");
    currentUrl = nextElement.GetAttribute("href");

我还建议将visitedUrls 更改为HashSet,而不是列表,因为它是一种更有效的数据结构,可以简单地确定一个项目是否在一组项目中。

【讨论】:

这也使用了 break - 它只是隐藏了它:) @Danvil No, actually it doesn't. 即使是这样,那也不是那么重要。您不负责维护FirstOrDefault。 MS 将确保它正常工作。在引擎盖下,所有循环都使用 GOTO。这没有错,但这并不意味着您应该使用 GOTO。在构建工具/抽象层时,您使用低级工具以便其他代码可以只使用高级工具,并避免使用低级工具的头痛。 @Danvil 谁在乎?编译器使用goto,但隐藏了它。重要的是“隐藏它”。即使break 仍然被使用,但被隐藏了,它造成的感知混乱(或 OP 正在使用的任何参数)也会被移除,因为它已经被抽象了。【参考方案2】:

如果您迭代一系列值并希望在找到满足条件的值后立即退出,通常使用 break:

foreach(var a in list) 
   if(test(a)) 
       // use a
       break;
   

有时它可能是不受欢迎的,您可以使用它:

bool found = false;
foreach(var a in list) 
   if(found && test(a)) 
       // use a
       found = true;
   

甚至:

bool found = false;
foreach(var a in list) 
   if(test(a)) 
       if(found) 
           // use a
           found = true;
       
   

一旦找到合适的元素,第一个版本可以跳过迭代。其他两个变体不断迭代甚至检查所有元素。在几乎所有情况下,这只会浪费处理能力。但是请查看此处,了解您实际上可能想要使用第三种变体的情况:http://en.wikipedia.org/wiki/Timing_attack

【讨论】:

以上是关于如何避免循环中断?的主要内容,如果未能解决你的问题,请参考以下文章

如何避免计时器滴答中断主线程?

如何从while循环内的if条件中断while循环?

如何在没有任何中断的情况下循环播放音频文件?

如何在while循环中手动中断光标?

如何中断或消除 inotifywait 循环?

中断for循环后如何重置指针