#c# #multithreading #listview #delegates
#c# #многопоточность #просмотр списка #делегаты
Вопрос:
У меня есть программа чтения новостей RSS, которая считывает rss-канал и записывает новости со ссылками в ListView. когда я выполняю свою программу, я запускаю новый поток, подобный этому:
Thread myThread = new Thread(getNews);
myThread.Start();
Мой метод чтения канала выглядит следующим образом:
public void getNews()
{
//Creates a XmlTextReader which reads from the url entered in input field
rssReader = new XmlTextReader(txtUrl.Text);
//Creates an xml doc to save the content of the entered path
rssDoc = new XmlDocument();
//Loads the xml content from the reader into a XmlDocument
rssDoc.Load(rssReader);
//Make a loop to search for the <rss> tag
for (int i = 0; i < rssDoc.ChildNodes.Count; i )
{
//If the childenode is the rss tag
if (rssDoc.ChildNodes[i].Name == "rss")
{
//the <rss> tag is found, and we know where it is
nodeRss = rssDoc.ChildNodes[i];
}
}
//Make a loop to search for the <channel> tag
for (int i = 0; i < nodeRss.ChildNodes.Count; i )
{
//If the childnode is the channel tag
if (nodeRss.ChildNodes[i].Name == "channel")
{
//The channel tag is found and we know where it is
nodeChannel = nodeRss.ChildNodes[i];
}
}
//Make a loop to search for the <item> tag
for (int i = 0; i < nodeChannel.ChildNodes.Count; i )
{
//If the childnode is the item tag
if (nodeChannel.ChildNodes[i].Name == "item")
{
//the item tag is found, and we know where it is
nodeItem = nodeChannel.ChildNodes[i];
//Creates a new row in the LstView which contains information from inside the nodes
rowNews = new ListViewItem();
rowNews.Text = nodeItem["title"].InnerText;
rowNews.SubItems.Add(nodeItem["link"].InnerText);
if (this.lstView.InvokeRequired)
{
AddItemCallback d = new AddItemCallback(getNews);
this.Invoke(d);
}
else
{
lstView.Items.Add(rowNews);
}
}
}
Моя проблема в том, что после того, как я начал запускать свой код в новом потоке и использовать делегат для проверки, запрашивает ли ListView вызов, все новостные ленты записываются в мой ListView несколько раз. если я запускаю метод без запуска нового потока и использую делегат, он записывается только один раз, почему это? Вероятно, это очень простой вопрос, но я просто не могу понять, почему
Заранее спасибо, примеры кода приветствуются 🙂
Ответ №1:
Вы установили проверку вызова в неправильном месте — таким образом, ваша функция getNews вызывается намного, намного больше раз, чем вы предполагали.
в самом верху getNews попробуйте следующее:
if (this.lstView.InvokeRequired) {
AddItemCallback d = new AddItemCallback(getNews);
this.Invoke(d);
return;
}
Затем замените оператор if в конце на lstView.Items.Add(rowNews);
Конечно, выполнение этого таким образом эффективно перенаправляет ваши getNews в поток пользовательского интерфейса. Что вам действительно нужно, так это создать коллекцию элементов ListViewItems и передать эту коллекцию методу обновления .. и в ЭТОМ методе вы проверяете, требуется ли вызов.
Комментарии:
1. Хм, да, кажется, работает, но приложения действуют так, как будто я не использую поток, поэтому при поиске новостной ленты я не могу с ней взаимодействовать. Можете ли вы привести пример того, что вы подразумеваете под созданием метода обновления?
Ответ №2:
Если требуется invoke, вы снова вызываете метод getNews. Вместо использования этого кода:
if (this.lstView.InvokeRequired)
{
AddItemCallback d = new AddItemCallback(getNews); // STOP CALLING getNews
this.Invoke(d);
}
Вам нужно вызвать другой метод для обновления вашего пользовательского интерфейса. Это гигантский цикл.