#c# #winforms #timer
#c# #winforms #таймер
Вопрос:
Я создаю программу для чтения RSS, я хочу, чтобы она могла обновляться через определенный интервал времени. Я не заинтересован в использовании компонента Winforms Timer. Я больше думал об использовании System.Threading.Timer
.
Метод, который я хочу выполнить с интервалом, выглядит следующим образом:
public void getNews()
{
for (int i2 = 0; i2 < urlList.Count; i2 )
{
//Creates a XmlTextReader which reads from the url entered in input field
rssReader = new XmlTextReader(urlList[i2]);
//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);
return;
}
lstView.Items.Add(rowNews);
}
}
}
}
Это кнопка, которая выполняет метод:
private void btnRead_Click(object sender, EventArgs e)
{
lstView.Items.Clear();
Thread myThread = new Thread(getNews);
myThread.Start();
}
Как мне выполнить мой getNews()
метод с определенным интервалом? Примеры с моим кодом очень ценятся.
Ответ №1:
Пользователь управляет таймером и пишет код в событии Tick… http://www.c-sharpcorner.com/UploadFile/mahesh/WorkingwithTimerControlinCSharp11302005054911AM/WorkingwithTimerControlinCSharp.aspx
Комментарии:
1. Если бы вы прочитали первую строку в моем сообщении, вы бы увидели, что это не то, что я хочу сделать.
Ответ №2:
Я бы запустил новый поток и перешел в режим ожидания на указанный интервал в конце его.
например
у вас была бы переменная-член, указывающая, запущен ли процесс, и интервал
private bool _isRunning = false;
private int _interval = 1000;
затем в вашем методе start создайте новый поток
public void Start()
{
ThreadStart oThreadStart = new ThreadStart(DoWork);
Thread t = new Thread(oThreadStart);
_isRunning = true;
t.Start();
}
public void Stop()
{
_isRunning = false;
}
private void DoWork()
{
while(_isRunning)
{
// do work
Thread.Sleep(_interval);
}
Thread.CurrentThread.Join();
}
Затем вся обработка выполняется в одном потоке, и он переходит в спящий режим, пока не используется (например, в ожидании следующего «тика»)
кроме того, использование этого метода предотвращает возможность запуска второго события tick до завершения обработки первого
Комментарии:
1. Это работает, но не так, как предполагалось, вся моя программа зависает, пока поток находится в режиме ожидания, и это не совсем то, что я хочу сделать
2. Вся ваша программа зависает? он не должен этого делать. Использовали ли вы Thread. currentThread. Спящий режим в другом месте? единственный поток, который должен находиться в режиме ожидания, — это поток, который вы запускаете для обработки
Ответ №3:
Мне нравятся реактивные расширения для этих вещей.
var observable = Observable.Interval(TimeSpan.FromSeconds(2)); // Interval in seconds
var subscription = observable.Subscribe(_ => getNews());
// Or if it does not work then try this:
var subscription = observable.ObserveOnWindowsForms().Subscribe(_ => getNews());
using (subscription)
{
Console.WriteLine("Press any key to stop...");
Console.ReadKey();
}
Вместо остановки нажатием клавиши консоли, вы можете вызвать .Dispose()
on subscription
и удалить весь using
блок.
Для тестирования этого подхода попробуйте заменить _ => getNews()
на Console.WriteLine
, и тогда вы увидите, как это работает 🙂 (это пример из http://rxwiki .wikidot.com/101samples )