为什么我的异步程序会抛出NullReferenceException

时间:2018-04-23 18:05:37

标签: c# async-await task

我得到以下异常:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object. at GoogleProducts.Program.<Main>d__0.MoveNext() in C:\Code\test\GoogleProducts\Program.cs:line 60 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at GoogleProducts.Program.<Main>(String[] args)

来源是:

private static async Task Main(string[] args)
        {
            var queries = new[]
            {
                "seico watch",
                "citizen watch",
                "orient watch",
                "bulova watch",
                "seagull watch",
                "glashuette watch"
            };

            var client = new WebClient();

            foreach (var query in queries)
            {
                var url = @"https://www.google.co.uk/search?tbm=shop&q=" + query;
                var content = await client.DownloadStringTaskAsync(url);

                var doc = new HtmlDocument();
                doc.LoadHtml(content);

                var linkedProducts = doc.DocumentNode.Descendants("a")
                    .Select(a => a.GetAttributeValue("href", null))
                    .Where(href => href.StartsWith(@"/shopping/product/"));

                var productTasks = linkedProducts.Select(async linkedProduct =>
                {
                    var productUrl = @"https://www.google.co.uk" + linkedProduct;

                    var productPage = await client.DownloadStringTaskAsync(productUrl);
                    var productDoc = new HtmlDocument();
                    productDoc.LoadHtml(productPage);

                    var productName = productDoc.DocumentNode.Descendants("title").FirstOrDefault()?.InnerText;

                    var sellersNodes = productDoc.DocumentNode.Descendants("tr")
                        .Where(tr => tr.GetAttributeValue("class", null) == "os-row");

                    var sellers = sellersNodes.Select(seller => new Seller
                    {
                        Name = seller.Descendants("a").First().InnerText,
                        Price = decimal.Parse(seller.Descendants("td").Last().InnerText.Substring(2))
                    }).ToArray();

                    return sellers.Any() ? new Product(sellers, productName) : null;
                }).Where(product => product != null);

                foreach (var productTask in productTasks)
                {
                    var product = await productTask;
                    var result =
                        $"{product.Name}{Environment.NewLine}Best price: {product.BestPrice()}, from {product.BestPriceSellers()}"
                        + $", Average price: {product.AveragePrice()}";

                    Console.WriteLine(result + Environment.NewLine);
                }
            }
        }

无法发布更多详情。

1 个答案:

答案 0 :(得分:3)

您正在).Where(product => product != null);列表中执行Task<Product>,而不是Product

因此,即使Product为null,Task<Product>也不是。

要更好地查看,请指定类型:

 .Where((Task<Product> product) => product != null);

这应该编译并告诉你错误的命名如何欺骗你。