2014-01-06 75 views
0

我有一個獨立的應用程序,它創建了許多線程來執行與我們的服務器之間的各種事務。其中一個線程在給定的時間間隔內輪詢服務器。我已經把Thread.Sleep(user_supplied_time_interval)用於讓輪詢線程在下一次輪詢嘗試之前等待給定的時間間隔。現在在結束申請期間,我想要Abort()所有的線程。爲此,我繼續參考parentThread中的輪詢線程,並在parentThread中調用pollerThread.Abort(); pollerThread.Join();。不過,我已經知道,我不能放棄睡眠線程。所以我得到System.Threading.ThreadAbortException在線Thread.Sleep(user_supplied_time_interval)。 我明顯可以設置一些布爾值來反映該輪詢器是否打算停止,並檢查布爾線程一旦線程退出睡眠狀態。但是,如果輪詢間隔很長,這也會延長應用程序退出,因爲輪詢器只有在退出睡眠狀態後纔會返回。在C中中止睡眠線程#

這個問題的標準解決方案是什麼?或者我應該分別抓住System.Threading.ThreadAbortException並忽略它。

+2

'Sleep'是邪惡的。 – Novak

+1

使用'Timer'而不是'Sleep'。 –

+0

@HamletHakobyan喜歡?請舉例。它不會消耗CPU週期嗎? – Mahesha999

回答

0

Thread.Abort不是一個好主意。

設置你的線程background工作:

pollerThread.IsBackground = true; 

後臺線程是相同的前臺線程,除了 後臺線程不會阻止進程的終止。

1

定時器舉例: 定時器運行每2秒

Timer t = new Timer(TimerCallback, null, 0, 2000); 

private void TimerCallback(Object o) 
{ 
    //Run some code here 
} 
2

你應該避免Thread.Abort的不惜一切代價,它可能會導致所有種類的奇怪的事情發生。

您可以使用ManualRestEvent代替等待超時事件與睡眠非常相似,您可以隨時用ManualRestEvent.Set喚醒。

你甚至可以對所有線程使用相同的事件,並且它可以作爲退出標誌加倍。

+0

如果要獨佔訪問資源,還有'AutoResetEvent'。如前所述,您應該避免使用'Thread.Abort'。線程應該以完成的方式退出(無論成功,取消還是異常),或者如果長時間運行則停留在循環中。 – Erik

0

在你的班級管理線程添加此屬性。

/// <summary> 
    /// Used to tell the thread to exit. 
    /// </summary> 
    private readonly AutoResetEvent _eventDelay; 

    /// <summary> 
    /// True if the worker thread is running. 
    /// </summary> 
    private bool _isRunning; 

在構造函數中像這樣初始化事件。

 _eventDelay = new AutoResetEvent(false); 

你的工作線程裏面,當它需要睡覺可以暫停的執行這樣的。

 _isRunning = true; 
     while(_isRunning) 
     { 
      // do thread work stuff 

      if(!_isRunning) 
      { 
       continue; 
      } 
      TimeSpan delay = // calculate how long the thread should sleep 
      _eventDelay.WaitOne(delay); 
     } 

您現在可以爲您的工人類使用ShutDown方法。請注意,它不會停止線程,直到它完成一次工作迭代。

/// <summary> 
    /// Flags the job to shutdown. It will stop execution 
    /// as soon as possible. 
    /// </summary> 
    public void ShutDown() 
    { 
     if (!_isRunning) 
     { 
      return; 
     } 

     _isRunning = false; 
     _eventDelay.Set(); 
    } 
0

我會強烈建議您使用無功擴展框架(Rx)的用於這種設置。根據間隔創建一個觀察值。當您不再需要輪詢時,您可以處理訂閱,並且框架將爲您清理。

看一看這個例子中,它應該讓你對你的方式:http://rxwiki.wikidot.com/101samples#toc28