¿Cómo repito hilo con intervalo exacto? C#

programación


C#
 private volatile bool _pause = false;
 private ManualResetEvent _pauseEvent = new ManualResetEvent(true);
 private Thread m_thread;
 private bool _istoday = true;
 private bool _isTimer_stop = false;
 private bool _thread_start = true;

private void btn_start_Click(object sender, EventArgs e)
 {

     int timer_interval = (int)numeric_app_freequency.Value;

         timer1_Tick(sender, e);
         timer1.Interval = 60 * 1000 * timer_interval;
         timer1.Enabled = true;
         timer1.Start(); //

 }

 private void timer1_Tick(object sender, EventArgs e)
 {
     if (_thread_start == true)
       {
         _thread_start = false;
         _istoday = true;
         m_thread = new Thread(new ThreadStart(begin_thread));
         m_thread.Name = "thred_1";
         m_thread.IsBackground = true;
         m_thread.Start();

        }

 }

 private void begin_thread()
 {

     int pageNum = 1;

     while (_pauseEvent.WaitOne())
     {
         if (_istoday == true)
         {

             parse_trs(pageNum);
             pageNum++;

         }
         else
         {
             Textbox1.Text = "Work is done"; ;
             break;
         }

     }
     _autoEvent.Set();
 }

 private void parse_trs(int pageNum)
 {
     string str_pageNum = pageNum.ToString();

     string list_url = "http://somedomain.com/bbs/board.php?bo_table=funny&page=" + str_pageNum;

     WebClient client = new WebClient();
     string sourceUrl = client.DownloadString(list_url);

     HtmlAgilityPack.HtmlDocument mydoc = new HtmlAgilityPack.HtmlDocument();

     mydoc.LoadHtml(sourceUrl);


     HtmlNodeCollection tr_col = mydoc.DocumentNode.SelectNodes("/ html / body//div[@id="bo_list"]//table/tbody/tr");

     foreach (HtmlNode node in tr_col)
     {

         _pauseEvent.WaitOne();


         if (post_date == today_date)
         {

             Do work.......................................

         }
         else
         {
             _istoday = false;
             break;
         }

     }
 }

Lo que he probado:

He usado el bucle while en lugar del temporizador, pero la CPU se sobrecarga y la aplicación se congela.

Solución 1

Este es probablemente el peor diseño posible para obtener un comportamiento periódico o casi periódico de un hilo. Hay muchas razones para ello, no es necesario discutirlas todas. El costo de crear una nueva instancia de hilo e iniciarla es uno de los factores, pero, de lejos, no es el peor. Lo peor es la fácil posibilidad de estropearlo todo.

Una solución mucho mejor y sencilla sería crear solo un subproceso adicional y mantenerlo ejecutándose durante prácticamente toda la vida útil de la aplicación. Simplemente haga que se ejecute en un bucle “infinito” (de hecho, interrumpido sólo cuando la aplicación está a punto de cerrarse) y limite su actividad mediante el uso de un objeto de control de espera de evento.

Es importante entender que en la llamada WaitHandle.WaitOne el hilo pasa o se somete a un proceso especial estado de espera; se apaga y nunca se programa su ejecución hasta que se activa, lo que sucede en Thread.Abort, Thread.Interrupt, tiempo de espera y otros eventos, en particular, señalar el objeto de control de espera de otro hilo. De esta manera, el subproceso no gasta tiempo de CPU en estado de espera, no hay espera de giro, ni verificaciones periódicas del estado, nada.

Por favor mira: Clase EventWaitHandle (System.Threading)[^].

Por favor vea mis respuestas anteriores:
Hacer que el hilo del código sea seguro[^],
pausar hilo en ejecución[^],
ManualResetEvent y AutoResetEvent en hilo[^],
Ejecutar exactamente un trabajo/hilo/proceso en un servicio web que nunca terminará (asp.net)[^].

Preste especial atención a la técnica alternativa relacionada de utilizar una colección de bloqueo; No está relacionado con su pregunta inmediata, pero es importante comprenderlo.

Ahora volvamos a la repetición “periódica” por temporizador. No estoy seguro de que lo necesites de esta manera. Una alternativa sería simplemente repetir el fragmento de código en un hilo por sí solo, tomando el tiempo real actual de, por ejemplo, System.DateTime.Nowcálculo del próximo tiempo de ejecución y llamada Thread.Sleep con la duración adecuada. Pero si realmente necesita un temporizador (nuevamente, no sé por qué), su única función sería señalar el controlador de espera del evento llamando EventWaitHandle.Set(), que activa el hilo que espera en esta instancia de controlador de eventos. Tenga en cuenta que esta llamada es segura para subprocesos, a diferencia de casi cualquier otra llamada de algunos métodos. También tenga en cuenta que el evento del temporizador ocurre en algún hilo que no conoce (excepto uno realmente malo). System.Windows.Forms.Timer que invoca el controlador de ticks en el hilo de la interfaz de usuario, pero este “alivio” es su único beneficio; en la mayoría de los casos, nunca debe usarse, ya que el momento es terriblemente malo).

Ambas técnicas resuelven el mayor problema al que te puedas enfrentar. ¿Qué podría suceder si comienza algún procesamiento si el procesamiento causado por el tic del temporizador anterior aún no se ha completado? Puede resultar difícil imaginar todo el desastre posible. Las soluciones que sugiero están completamente libres de este problema.

-SA

コメント

タイトルとURLをコピーしました