Чтение многопоточного XML-файла
Я много искал, но я не мог найти правильное решение для моей проблемы. Я написал XML-файл, содержащий всю информацию о сериале ТВ-шоу. Это 38 КБ и содержит атрибуты и строки для около 680 переменных. Сначала я просто прочитал его с помощью XMLTextReader, который отлично работал с моим четырехъядерным процессором. Но моему жене, пятилетнему ноутбуку, потребовалось около 30 секунд, чтобы прочитать его. Поэтому я подумал о многопоточности, но получаю исключение, потому что файл уже открыт.
Начало потока выглядит так
while (reader.Read())
{
...
else if (reader.NodeType == XmlNodeType.Element)
{
if (reader.Name.Equals("Season1"))
{
current.seasonNr = 0;
current.currentSeason = season[0];
current.reader = reader;
seasonThread[0].Start(current);
}
else if (reader.Name.Equals("Season2"))
{
current.seasonNr = 1;
current.currentSeason = season[1];
current.reader = reader;
seasonThread[1].Start(current);
}
И метод синтаксического анализа, как это
reader.Read();
for (episodeNr = 0; episodeNr < tmp.currentSeason.episode.Length; episodeNr++)
{
reader.MoveToFirstAttribute();
tmp.currentSeason.episode[episodeNr].id = reader.ReadContentAsInt();
...
}
Но это не работает...
Я передаю читателю, потому что я хочу, чтобы курсор был в правильном положении. Но я также понятия не имею, может ли это вообще сработать.
Пожалуйста помоги!
РЕДАКТИРОВАТЬ: Ребята, где я написал о IE?? Программа, которую я написал, анализирует файл. Я запускаю его на своем ПК и на ноутбуке. Нет IE вообще.
РЕДАКТИРОВАТЬ 2: Я сделал некоторые исследования секундомера и выяснил, что анализ файла XML занимает всего около 200 мс на моем ПК и 800 мс на моем ноутбуке с жёнами. WPF работает так медленно? Что я могу сделать?
4 ответа
Я согласен с большинством всех комментариев. Чтение файла размером 38 КБ не должно занимать много времени. У вас на компьютере работает что-то еще, антивирус и т. Д., Которые могут мешать обработке?
Время, затрачиваемое на создание потока, будет намного больше, чем время, потраченное на чтение файла. Если бы вы могли опубликовать реальный код, использованный для чтения файла, и сам файл, это может помочь проанализировать узкие места производительности.
Я думаю, что вы не можете анализировать XML в нескольких потоках, по крайней мере, не таким образом, который принес бы выигрыш в производительности, потому что для чтения с некоторой точки в файле вам нужно знать все, что предшествует ему, если не сказать ничего, чтобы знать на каком ты уровне.
Ваш код, если бы работала синица, сделал бы что-то вроде этого:
main season1 season2
read
read
skip read
skip read
read
skip read
skip read
Обратите внимание, что для "пропуска" необходимо полностью проанализировать XML, что означает, что вы выполняете тот же объем работы, что и раньше, в основном потоке. Разница лишь в том, что вы выполняете дополнительную работу с фоновыми потоками.
Что касается медлительности, просто разбор такого маленького XML-файла должен быть очень быстрым. Если он медленный, вы, скорее всего, делаете что-то медленное или разбираете файл несколько раз.
Если я понимаю, как используется ваш файл.xml, вы по существу создали базу данных.xml.
Если все правильно, я бы порекомендовал разбить ваш Xml на разные XML-файлы с индексированным XML-документом. Я думаю, что вы можете запросить - используя Linq-2-Xml - набор данных.xml из определенного источника.xml.
Конечно, это означает, что вам все равно нужно будет загрузить файл.xml; однако вы будете загружать файлы значительно меньшего размера и сможете, хотя и не рекомендуется, асинхронно загружать объекты документов XML.
Ваша XML-схема не поддается параллелизму, поскольку у вас, кажется, есть имена узлов (Season1, Season2), которые содержат те же данные, но должны анализироваться по отдельности. Вы можете изменить схему, чтобы иметь одинаковые имена узлов (т.е. Season
) и атрибуты, которые выражают различия в данных (т.е. Number
указать номер сезона). Затем вы можете распараллелить, т.е. используя Linq to XML и PLinq:
XDocument doc = XDocument.Load(@"TVShowSeasons.xml");
var seasonData = doc.Descendants("Season")
.AsParallel()
.Select(x => new Season()
{
Number = (int)x.Attribute("Number"),
Descripton = x.Value
}).ToList();