Выполнение метода с интервалом в Winforms на C#

#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 )