即使放入数据后,字符串仍为null

时间:2014-03-20 20:09:46

标签: c# microsoft-metro html-parsing html-agility-pack

我是windows metro应用程序的新手,完全停留在这里。 textbox1.text显示函数内部的准确数据,但Aya在函数外部保持为null。我怎么解决这个问题 ?我认为递归会产生问题,但如何解决呢?

public async void Aya_Parse()
    {

        // Initialize http client.
        HttpClient httpClient = new HttpClient();
        Stream stream = await httpClient.GetStreamAsync("some link");

        // Load html document from stream provided by http client.
        HtmlDocument htmlDocument = new HtmlDocument();
        htmlDocument.OptionFixNestedTags = true;
        htmlDocument.Load(stream);

        Aya_ParseHtmlNode(htmlDocument.DocumentNode);
    }

    int aia = 0;
    string Aya = null;
    private void Aya_ParseHtmlNode(HtmlNode htmlNode)
    {

        foreach (HtmlNode childNode in htmlNode.ChildNodes)
        {


            if (childNode.NodeType == HtmlNodeType.Text && aia == 1)
            {

                Aya += " " + childNode.InnerText.ToString(); aia = 0;

            }

            else if (childNode.NodeType == HtmlNodeType.Element)
            {
               Aya += " "; // removing this causes null exception at textbox1.text 

                switch (childNode.Name.ToLower())
                {

                    case "span":
                        Aya += childNode.NextSibling.InnerText.ToString();

                       Aya_ParseHtmlNode(childNode);
                        break;
                    case "td":

                        aia = 1;
                        Aya_ParseHtmlNode(childNode);break;

                    default:

                        Aya_ParseHtmlNode(childNode); break;
                }
            }
        }
        textBox1.Text = Aya;

    }

2 个答案:

答案 0 :(得分:1)

您永远不会将起始值分配给Aya,因此即使您尝试在Aya_ParseHtmlNode(HtmlNode htmlNode)方法中向其添加文本,也无法将文本添加到空值。这可以通过检查值null并将其设置为默认值来解决。我很惊讶你没有在你的方法中得到NullArgumentException ......

public async void Aya_Parse()
{

    // Initialize http client.
    HttpClient httpClient = new HttpClient();
    Stream stream = await httpClient.GetStreamAsync("some link");

    // Load html document from stream provided by http client.
    HtmlDocument htmlDocument = new HtmlDocument();
    htmlDocument.OptionFixNestedTags = true;
    htmlDocument.Load(stream);
    //  greetingOutput.Text = htmlDocument.DocumentNode.InnerText.ToString();
    // Parse html node, this is a recursive function which call itself until
    // all the childs of html document has been navigated and parsed.
    Aya_ParseHtmlNode(htmlDocument.DocumentNode);
}

int aia = 0;
string Aya = null;
private void Aya_ParseHtmlNode(HtmlNode htmlNode)
{
    if (Aya == null)
    {
        Aya = String.empty;
    }
    foreach (HtmlNode childNode in htmlNode.ChildNodes)
    {


        if (childNode.NodeType == HtmlNodeType.Text && aia == 1)
        {

            Aya += " " + childNode.InnerText.ToString(); aia = 0;

        }

        else if (childNode.NodeType == HtmlNodeType.Element)
        {
           Aya += " ";

            switch (childNode.Name.ToLower())
            {

                case "span":
                    Aya += childNode.NextSibling.InnerText.ToString();

                   Aya_ParseHtmlNode(childNode);
                    break;
                case "td":

                    aia = 1;
                    Aya_ParseHtmlNode(childNode);break;

                default:

                    Aya_ParseHtmlNode(childNode); break;
            }
        }
    }
    textBox1.Text = Aya;

}

使用StringBuilder也可能是一个更好的主意,因为你可以在这里递归并生成一个非常大字符串,所以StringBuilder会更容易记忆

public void Aya_Parse()
{

    // Initialize http client.
    HttpClient httpClient = new HttpClient();
    Stream stream =  httpClient.GetStreamAsync("some link").Result;

    // Load html document from stream provided by http client.
    HtmlDocument htmlDocument = new HtmlDocument();
    htmlDocument.OptionFixNestedTags = true;
    htmlDocument.Load(stream);
    //  greetingOutput.Text = htmlDocument.DocumentNode.InnerText.ToString();
    // Parse html node, this is a recursive function which call itself until
    // all the childs of html document has been navigated and parsed.


    //you marked the method Async, and
    //since Aya is in the class, if multiple threads call this
    //method, you could get inconsistent results
    //I have changed it to a parameter here so this doesn't happen
    StringBuilder Aya = new StringBuilder()
    Aya_ParseHtmlNode(htmlDocument.DocumentNode, Aya);
    //I would also move your textbox update here, so you aren't calling
    //ToString() all the time, wasting all of the memory benefits
    textBox1.Text = Aya.ToString();
}

int aia = 0;
private void Aya_ParseHtmlNode(HtmlNode htmlNode, StringBuilder Aya)
{

    foreach (HtmlNode childNode in htmlNode.ChildNodes)
    {


        if (childNode.NodeType == HtmlNodeType.Text && aia == 1)
        {

            Aya.Append(childNode.InnerText); aia = 0;

        }

        else if (childNode.NodeType == HtmlNodeType.Element)
        {
           Aya.Append(" ");

            switch (childNode.Name.ToLower())
            {

                case "span":
                    Aya.Append(childNode.NextSibling.InnerText);

                   Aya_ParseHtmlNode(childNode, Aya);
                    break;
                case "td":

                    aia = 1;
                    Aya_ParseHtmlNode(childNode, Aya);break;

                default:

                    Aya_ParseHtmlNode(childNode, Aya); break;
            }
        }
    }
}

修改:您的问题实际上可能来自您在async上使用Aya_Parse()关键字,这意味着调用Aya_Parse()的方法可能会返回在实际进行任何处理之前立即。因此,如果在调用Aya后检查Aya_Parse()的值,则在您实际检查代码中的其他值之前,可能没有足够的时间进行计算。我建议删除async代码,或更改Aya_Parse()以在完成时返回Aya的值。请查看here,了解有关如何将async标记与返回值一起使用的一些详细信息。

答案 1 :(得分:0)

可能是。它的行为就好像你的字符串变量是按值传递给方法而不是保持引用。

请记住,通过使用Async方法,您实际上是多线程的,因此多个线程将竞争相同的模块级变量。编译器可能会选择让您的代码线程安全。

如果在异步方法中声明一个单独的字符串并通过ref传递它,则应该按预期运行。

我还建议您对模块级别int执行相同操作。

或者...你可以从Aya_Parse中删除异步并使用任务库(并在下面的等待调用中投掷)来获取你的流。