我是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;
}
答案 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中删除异步并使用任务库(并在下面的等待调用中投掷)来获取你的流。