[ad_1]
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; } } }
Ce que j’ai essayé :
J’ai utilisé la boucle while au lieu de la minuterie mais le processeur surcharge donc l’application se bloque
Solution 1
C’est probablement la pire conception possible pour obtenir un comportement périodique ou quasi périodique d’un thread. Il y a de nombreuses raisons à cela, il n’est pas nécessaire de toutes les aborder. Le coût de création d’une nouvelle instance de thread et de son démarrage est l’un des facteurs, mais ce n’est de loin pas le pire. Le pire, c’est la possibilité de tout gâcher.
Une solution bien plus simple serait de créer un seul thread supplémentaire et de le maintenir en exécution pendant presque toute la durée de vie de l’application. Vous le faites simplement s’exécuter dans une boucle “infinie” (en fait, interrompue uniquement lorsque l’application est sur le point de se fermer) et limitez son activité en utilisant un objet de poignée d’attente d’événement.
Il est important de comprendre que lors de l’appel WaitHandle.WaitOne
le fil soit passe, soit est placé dans un dossier spécial état d’attente; il est éteint et son exécution n’est jamais programmée jusqu’à ce qu’il soit réveillé, ce qui se produit le Thread.Abort
, Thread.Interrupt
, le délai d’attente et d’autres événements, en particulier signalant l’objet de poignée d’attente d’un autre thread. De cette façon, le thread ne passe aucun temps CPU en état d’attente, il n’y a pas d’attente de rotation, pas de vérifications périodiques de l’état, rien.
S’il te plait regarde: Classe EventWaitHandle (System.Threading)[^].
Veuillez consulter mes réponses précédentes :
Rendre le fil de code sûr[^],
mettre le fil en cours d’exécution[^],
ManualResetEvent et AutoResetEvent dans le fil de discussion[^],
Exécuter exactement un travail/thread/processus dans un service Web qui ne sera jamais terminé (asp.net)[^].
Portez une attention particulière à la technique alternative associée consistant à utiliser une collection de blocage ; cela n’a aucun rapport avec votre question immédiate mais il est important de comprendre.
Revenons maintenant à la répétition « périodique » par timer. Je ne suis pas sûr que vous en ayez besoin de cette façon. Une alternative serait simplement de répéter le morceau de code dans un fil de discussion, en prenant le temps réel actuel, par exemple : System.DateTime.Now
calcul du prochain temps d’exécution et appel Thread.Sleep
avec une durée appropriée. Mais si vous avez vraiment besoin d’une minuterie (encore une fois, je ne sais pas pourquoi), sa seule fonction serait de signaler le handle d’attente de l’événement en appelant EventWaitHandle.Set()
, qui réveille le thread en attente sur cette instance de handle d’événement. Notez que cet appel est thread-safe, contrairement à presque tous les autres appels de certaines méthodes. Notez également que l’événement timer se produit dans un thread que vous ne connaissez pas (sauf très mauvais System.Windows.Forms.Timer
qui invoque le gestionnaire de ticks dans le thread de l’interface utilisateur, mais ce “soulagement” est son seul avantage ; dans la plupart des cas, il ne faut jamais l’utiliser, car le timing est terriblement mauvais).
Les deux techniques résolvent le plus gros problème auquel vous pourriez être confronté. Que pourrait-il se passer si vous démarrez un traitement si le traitement provoqué par votre précédent tick de minuterie n’est pas encore terminé ? Il peut être difficile d’imaginer tout le désordre possible. Les solutions que je propose sont totalement exemptes de ce problème.
[ad_2]
コメント