1 / 1 / 1
Регистрация: 22.11.2015
Сообщений: 139

NullReferenceException при использовании PLINQ

16.03.2017, 19:38. Показов 1929. Ответов 10

Студворк — интернет-сервис помощи студентам
Добрый день, проблема заключается в том,что при парсинге сайта с помощью HtmlAgilityPack. Метод SelectNode может вернуть null( парсю 1000 однотипных страниц, в которых точно есть определенный тег).

Создаю несколько потоков наподобие этого. result - хранит html страницы. В методе CreateTagAndWrite _pricetag может быть равен null не понимаю по какой причине.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  
Parallel.Invoke(
 
                () =>
                {
                    Console.WriteLine("Start Women1");
                    Stopwatch stopWatch = new Stopwatch();
                    stopWatch.Start();
                    var result = GetAllPageInGroup(_rpages.ElementAt(0));
                    result.AsParallel().ForAll(item =>
                    {
                        CreateTagAndWrite(item, "Women1");
                    });
                    stopWatch.Stop();
                    TimeSpan ts = stopWatch.Elapsed;
                    string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                        ts.Hours, ts.Minutes, ts.Seconds,
                        ts.Milliseconds / 10);
                    Console.WriteLine("Women1" + " " + "RunTime " + elapsedTime);
                },
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 public static void CreateTagAndWrite(string htmlpage, string file_name)
{
 List<string> ListTag = new List<string>();
            HtmlAgilityPack.HtmlDocument html_document = new HtmlAgilityPack.HtmlDocument();
            try
            {
                string _tempitem = "";
                MemoryStream ms = new MemoryStream(Encoding.Default.GetBytes(htmlpage));
                html_document.Load(ms);
                ms.Close();
                if (html_document.DocumentNode != null)
                {
                    var _pricetag = html_document.DocumentNode.SelectNodes("//div[@class='to-favorites js-to-favorites']");
                    var _hreftag = html_document.DocumentNode.SelectNodes("//div[@class='products-list-item']/a");
                    var price = ReturnMyAttribute(_pricetag, "data-price", requires).ToList();
                    var image = ReturnMyAttribute(_pricetag, "data-image", requires).ToList();
                    var href = ReturnMyAttribute(_hreftag, "href", requires).ToList();
                }
            }
}
Если AgilityPack не поддерживает асинхронные операции ,надо ли сделать обертку для вызова SelectNodes или это не исправит проблему? Мне кажется ,что это явно "г*внокод" , посоветуйте, как правильно использовать многопоточность для этой ситуации

Добавлено через 4 часа 42 минуты
Up,Up

Добавлено через 3 часа 46 минут
Up
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
16.03.2017, 19:38
Ответы с готовыми решениями:

[Compact Framework] Ошибка при использовании OpenNETCF.Net.Ftp.FTPWebResponse(): NullReferenceException
Доброго времени суток господа! Вопрос следующий. Использую Compact Framework и для работы с FTP соответственно библиотеку...

Ошибка NullReferenceException при добавлении
Изучаю asp. net core. И не знаю как исправить ошибку при добавлении нового работника. Код HomeController: public class...

NullReferenceException при поиске в DataGridView
Есть вот такой код - Когда я ввожу какие-либо данные в textbox, чтобы произвести поиск с выделением, то у меня выдает ошибку (ошибка на...

10
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18286 / 14209 / 5368
Регистрация: 17.03.2014
Сообщений: 28,888
Записей в блоге: 1
17.03.2017, 00:42
Jexio, т.к. метод CreateTagAndWrite оперирует только локальными переменными, то это не похоже на проблемы вызванные многопоточностью. Может на странице точно нет таких элементов?
0
Эксперт .NET
 Аватар для Usaga
14145 / 9374 / 1350
Регистрация: 21.01.2016
Сообщений: 35,307
17.03.2017, 06:02
Цитата Сообщение от Jexio Посмотреть сообщение
может быть равен null не понимаю по какой причине.
Есть какие-то объективные причины не использовать отладчик для выявления проблемы?..
0
1 / 1 / 1
Регистрация: 22.11.2015
Сообщений: 139
17.03.2017, 10:44  [ТС]
//Компилирую в голове.
Проходил отладчиком, SelectNodes вернул null ,но на странице имелся этот тэг. Поэтому и написал ,что не понимаю по какой причине получил null
0
Эксперт .NET
 Аватар для Usaga
14145 / 9374 / 1350
Регистрация: 21.01.2016
Сообщений: 35,307
17.03.2017, 10:55
Jexio, а ты в отладчике смотрел, что приходит в htmlpage? Ты уверен, что выражение в SelectNodes корректное?
0
1 / 1 / 1
Регистрация: 22.11.2015
Сообщений: 139
17.03.2017, 13:58  [ТС]
htmlpage - не пустая, не равна null и содержит данный тег. Проблема возникает ,когда я запускаю несколько потоков ,которые выполняют этот участок кода
C#
1
2
3
4
result.AsParallel().ForAll(item =>
                    {
                        CreateTagAndWrite(item, "Women1");
                    });
Если запускаю 1 поток, то NullReference не возникает.
0
 Аватар для EveKS
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
17.03.2017, 14:57
Jexio, можно увидеть чуть больше кода? или там не что-то сверхсекретное конечно...

Добавлено через 25 минут
Jexio, в общем, нужен весь код или что и откуда берется - сделаю в один метод Linq запросом, заверну в Task, если надо, добавлю токены, чтоб остановить поток, ну и всё это будет работать без ошибок.
И всё это будет привязано к модели...
0
1 / 1 / 1
Регистрация: 22.11.2015
Сообщений: 139
17.03.2017, 15:11  [ТС]
проприетарный протокол ,строго секретно)
C#
1
2
3
4
5
6
7
8
9
10
11
public static readonly object locker = new object();
        public static Page _pageWomen;
        public static Page _pageMen;
        public static Page _pageChild;
        public static Func<HtmlAgilityPack.HtmlAttribute, string, bool> requires = AlgorithmCheck;
        public static string SystemDisk = Environment.GetFolderPath(Environment.SpecialFolder.System);
        public static string LocalPath = string.Empty;
static void Main(string[] args)
        {
Task.Factory.StartNew(async ()=> { await StartWomen(); });
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public async static Task StartWomen()
        {
            await SetChildMainPage(_pageWomen);
            var currentpage = GetFullChildPage(_pageWomen, 3).GetChildForIndex(3);
            IEnumerable<Page> _pages = from _npage in currentpage.GetAllChild() select _npage;
            List<Page> _rpages = _pages.ToList();
            Console.WriteLine("Start");
            Parallel.Invoke(
 
                () =>
                {
                    Console.WriteLine("Start Women1");
                    Stopwatch stopWatch = new Stopwatch();
                    stopWatch.Start();
                    var result = GetAllPageInGroup(_rpages.ElementAt(0));
                    result.AsParallel().ForAll(item =>
                    {
                        CreateTagAndWrite(item, "Women1");
                    });
                    stopWatch.Stop();
                    TimeSpan ts = stopWatch.Elapsed;
                    string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                        ts.Hours, ts.Minutes, ts.Seconds,
                        ts.Milliseconds / 10);
                    Console.WriteLine("Women1" + " " + "RunTime " + elapsedTime);
                },
                () =>
                {
                    Console.WriteLine("Start Women2");
                    Stopwatch stopWatch = new Stopwatch();
                    stopWatch.Start();
                    var result = GetAllPageInGroup(_rpages.ElementAt(1));
                    result.AsParallel().ForAll(item =>
                    {
                        CreateTagAndWrite(item, "Women2");
                    });
                    stopWatch.Stop();
                    TimeSpan ts = stopWatch.Elapsed;
                    string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                        ts.Hours, ts.Minutes, ts.Seconds,
                        ts.Milliseconds / 10);
                    Console.WriteLine("Women2" + " " + "RunTime " + elapsedTime);
                }
);
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static List<string> GetAllPageInGroup(Page page)
        {
            int countpage = 0;
            string curUri = page.myUri.AbsoluteUri;
            string html = "";
            Regex regex = new Regex(@"\d{1,5}(?=\S\WperPage)");
            html = getRequestAsync(page.myUri.AbsoluteUri).Result;
            Match match = regex.Match(html);
            while (match.Success)
            {
                Int32.TryParse(match.Value, out countpage);
                match = match.NextMatch();
            }
            List<string> HtmlList = new List<string>();
            using (var enumerator = Enumerable.Range(1, countpage).GetEnumerator())
            {
                while (enumerator.MoveNext())
                {
                    HtmlList.Add(getRequestAsync(curUri + "&page=" + enumerator.Current.ToString()).Result);
                }
            }
            return HtmlList;
        }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public static void CreateTagAndWrite(string href, string file_name)
        {
            var result = GetAllTagInPage(href);
            WriteTagInXMLFile(result, file_name);
        }
 public static List<string> GetAllTagInPage(string htmlpage)
        {
            List<string> ListTag = new List<string>();
            HtmlAgilityPack.HtmlDocument html_document = new HtmlAgilityPack.HtmlDocument();
            try
            {
                string _tempitem = "";
                MemoryStream ms = new MemoryStream(Encoding.Default.GetBytes(htmlpage));
                html_document.Load(ms);
                ms.Close();
                if (html_document.DocumentNode != null)
                {
                    var _pricetag = html_document.DocumentNode.SelectNodes("//div[@class='to-favorites js-to-favorites']");
                    var _hreftag = html_document.DocumentNode.SelectNodes("//div[@class='products-list-item']/a");
                    var price = ReturnMyAttribute(_pricetag, "data-price", requires).ToList();
                    var image = ReturnMyAttribute(_pricetag, "data-image", requires).ToList();
                    var href = ReturnMyAttribute(_hreftag, "href", requires).ToList();
                    if (price != null && href != null && image != null)
                    {
                        for (int count = 0; count < price.Count; count++)
                        {
                            _tempitem = price[count] + " " + PrefixSite.lamoda + href[count] + " " + image[count];
                            ListTag.Add(_tempitem);
                            _tempitem = string.Empty;
 
                        }
                    }
                   // _pricetag = null;
                   // _hreftag = null;
                  //  price = null;
                  //  image = null;
                  //  href = null;
                }
            }
            catch (NullReferenceException exception)
            {
                Console.WriteLine(exception.Message);
               // Console.WriteLine(GC.GetTotalMemory(false));
                return new List<string>();
            }
            catch(OutOfMemoryException exception)
            {
                Console.WriteLine(exception.Message);
                Console.WriteLine(GC.GetTotalMemory(false));
                return new List<string>();
            }
            finally
            {
                html_document = null;
            }
            return ListTag;
        }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 public async static Task<string> getRequestAsync(string url)
        {
            Task<string> get = Task.Run(
                () =>
                {
                    try
                    {
                        var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
                        httpWebRequest.AllowAutoRedirect = false;//Запрещаем автоматический редирект
                        httpWebRequest.Method = "GET"; //Можно не указывать, по умолчанию используется GET.
                        httpWebRequest.Referer = "http://google.com"; // Реферер. Тут можно указать любой URL
 
                        using (var httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse())
                        {
                            using (var stream = httpWebResponse.GetResponseStream())
                            {
                                using (var reader = new StreamReader(stream, Encoding.GetEncoding(httpWebResponse.CharacterSet)))
                                {
                                    return reader.ReadToEnd();
                                }
                            }
                        }
                    }
                    catch
                    {
                        return String.Empty;
                    }
                }
 
                );
            var result = await get.ConfigureAwait(false);
            return result;
        }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static bool AlgorithmCheck(HtmlAgilityPack.HtmlAttribute attribute, string Name)
        {
            return attribute.Name == Name;
        }
        public static IEnumerable<string> ReturnMyAttribute(HtmlAgilityPack.HtmlNodeCollection dataSource, string NameAttribute, Func<HtmlAgilityPack.HtmlAttribute, string, bool> predicate)
        {
            foreach (var item in dataSource)
            {
                foreach (var attribute in item.Attributes)
                {
                    if (predicate(attribute, NameAttribute)) yield return attribute.Value;
                }
            }
        }
0
 Аватар для EveKS
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
17.03.2017, 17:21
Лучший ответ Сообщение было отмечено Jexio как решение

Решение

Кликните здесь для просмотра всего текста
Jexio, =)) что-за любовь к именам внутри методов в виде _name... Поля именуют _name, переменные в методах без _, а если эти переменные связаны с полями, то мы просто убираем _, например var name = Foo(_name);, ну или наоборот, ну да ладно...
Что это:
C#
1
2
3
4
5
6
7
public static Func<HtmlAgilityPack.HtmlAttribute, string, bool> requires = AlgorithmCheck;
// МногА кодА
 
        public static bool AlgorithmCheck(HtmlAgilityPack.HtmlAttribute attribute, string Name)
        {
            return attribute.Name == Name;
        }
Не понятно=)))


В общем, почему именно так:
public async static Task<string> getRequestAsync(string url)
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
        public async static Task<string> getRequestAsync(string url)
        {
            Task<string> get = Task.Run(
                () =>
                {
                    try
                    {
                        var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
                        httpWebRequest.AllowAutoRedirect = false;//Запрещаем автоматический редирект
                        httpWebRequest.Method = "GET"; //Можно не указывать, по умолчанию используется GET.
                        httpWebRequest.Referer = "http://google.com"; // Реферер. Тут можно указать любой URL
 
                        using (var httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse())
                        {
                            using (var stream = httpWebResponse.GetResponseStream())
                            {
                                using (var reader = new StreamReader(stream, Encoding.GetEncoding(httpWebResponse.CharacterSet)))
                                {
                                    return reader.ReadToEnd();
                                }
                            }
                        }
                    }
                    catch
                    {
                        return String.Empty;
                    }
                }
 
                );
            var result = await get.ConfigureAwait(false);
            return result;
        }


Что если:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        private async Task<string> GetHttpAsync(string requestUri)
        {
            //string userAgentString =
            //    "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko";
            var httpMessage = new HttpClientHandler()
            {
                AllowAutoRedirect = false,
            };
            using (var client = new HttpClient(httpMessage))
            {
                //client.DefaultRequestHeaders.Add("User-Agent", userAgentString);
                return await client.GetStringAsync(requestUri);
            }
        }
Далее, там, как я понимаю этот метод GetAllPageInGroup возвращает список uri. Метод StartWomen производит манипуляции с этими списками.

Есть вариант сделать подобные методы:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        public IEnumerable<Task<IEnumerable<ClassName>>> PageParserAsync(IEnumerable<string> pageUri)
            => pageUri.Select(async uri => await GetHttpAsync(uri))
            .Select(async content =>
            {
                HtmlDocument document = new HtmlDocument();
                document.LoadHtml(await content);
 
                var pricetag = document.DocumentNode.SelectNodes("//div[@class='to-favorites js-to-favorites']");
                var hreftag = document.DocumentNode.SelectNodes("//div[@class='products-list-item']/a");
 
                return pricetag.Select((element, index) =>
                new ClassName
                {
                    Price = element.Attributes["data-price"].Value ?? "",
                    Image = element.Attributes["data-image"].Value ?? "",
                    Href = hreftag.Select(node => node.Attributes["href"].Value).ElementAt(index) ?? ""
                });
            });
Или:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        public Task<IEnumerable<ClassName>> PageParserAsync(string pageUri)
            => Enumerable.Range(0, 1)
                .Select(async _ => await GetHttpAsync(pageUri))
            .Select(async content =>
            {
                HtmlDocument document = new HtmlDocument();
                document.LoadHtml(await content);
 
                var pricetag = document.DocumentNode.SelectNodes("//div[@class='to-favorites js-to-favorites']");
                var hreftag = document.DocumentNode.SelectNodes("//div[@class='products-list-item']/a");
 
                return pricetag.Select((element, index) =>
                new ClassName
                {
                    Price = element.Attributes["data-price"].Value ?? "",
                    Image = element.Attributes["data-image"].Value ?? "",
                    Href = hreftag.Select(node => node.Attributes["href"].Value).ElementAt(index) ?? ""
                });
            }).First();
Класс:
C#
1
2
3
4
5
6
    public class ClassName
    {
        public string Image { get; set; }
        public string Href { get; set; }
        public string Price { get; set; }
    }

Не по теме:

Яб всё сделал по другому. Есть и другие библиотеки, помимо HtmlAgilityPack

1
1 / 1 / 1
Регистрация: 22.11.2015
Сообщений: 139
17.03.2017, 18:43  [ТС]
А по-другому это как? Опишите ваш "алгоритм", пожалуйста.
0
 Аватар для EveKS
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
17.03.2017, 19:18
Вынес Regex как отдельный метод, затем через этот метод получал список нужных Uri и делал с ними нужные манипуляции, затем выводил или что там нужно.

Почему все поля открытые???

StartWomen Почему там всё так? Parallel.Invoke( /// А если бы у нас было 1500 элементов, во что бы превратилось это?
Почему не разбить всё это на несколько методов.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//Зачем это поле вообще?
public static Func<HtmlAttribute, string, bool> requires = AlgorithmCheck;
// далее
 
public static bool AlgorithmCheck(HtmlAgilityPack.HtmlAttribute attribute, string Name)
        {
            return attribute.Name == Name;
        }
        public static IEnumerable<string> ReturnMyAttribute(HtmlAgilityPack.HtmlNodeCollection dataSource, string NameAttribute, Func<HtmlAgilityPack.HtmlAttribute, string, bool> predicate)
        {
            foreach (var item in dataSource)
            {
                foreach (var attribute in item.Attributes)
                {
                    if (predicate(attribute, NameAttribute)) yield return attribute.Value;
                }
            }
        }
Если можно обойтись:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    public static bool AlgorithmCheck(HtmlAttribute attribute, string name)
    {
        return attribute.Name == name;
    }
 
    public static IEnumerable<string> ReturnMyAttribute(HtmlNodeCollection dataSource, string nameAttribute)
    {
        foreach (var item in dataSource)
        {
            foreach (var attribute in item.Attributes)
            {
                if (AlgorithmCheck(attribute, nameAttribute))
                {
                    yield return attribute.Value;
                }
            }
        }
    }
Или проще:
C#
1
2
3
    public static IEnumerable<string> ReturnMyAttribute(HtmlNodeCollection dataSource, string nameAttribute)
        => dataSource.SelectMany(item => item.Attributes.Where(attribute => attribute.Name == nameAttribute)
                                                        .Select(attribute => attribute.Value));
И, даже, всё это тоже лишнее...
Если есть:
C#
1
.Attributes["data-price"].Value
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
17.03.2017, 19:18
Помогаю со студенческими работами здесь

NullReferenceException при клике на ComboBox
Добрый день! Форма работает нормально пока не кликаю по ComboBox. Выдает ошибку: А код такой: using System; using...

NullReferenceException при вызове делегата
/// Создан новый класс. public static void ParsGrups() { var form = Form1.ActiveForm as Form2; ...

NullReferenceException при редактировании данных
Добрый день. Данная программа работает с базой данных через wf. Пока что реализованы кнопки добавить и редактировать (они выделены...

NullReferenceException при добавлении картинки
@model GameSite.Models.Game_description @{ ViewData = &quot;Contact&quot;; } &lt;body&gt; &lt;div class=&quot;container&quot;&gt; &lt;div...

Ошибка при использовании Contains: "NullReferenceException: Object reference not set to an instance of an object"
string a = &quot;aaaaa&quot;; string b = &quot; bbb&quot;; bool c = a.Contains (b); Выводит ошибку в 3 строке &quot;NullReferenceException: Object...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru