2010-07-22 36 views
3

我有一個我想使用的System.Timers.Timer對象,但我不希望綁定到Timer的處理過程干擾正常到高優先級的線程。換句話說,我想說,只要沒有別的東西在運行,我想每5秒鐘處理一次X0 Timer Elapsed事件如何與高優先級線程競爭?

我怎麼能保證我的定時器操作在一個低優先級的方式運行?

回答

2

有關System.Timers.Timer的好處是您可以通過SynchronizingObject屬性分配同步對象,然後利用它來運行Elapsed事件可以控制其優先級的線程。

ElapsedEventReceiver的實例只是分配給你的計時器的SynchronizingObject財產。

免責聲明:我掀起這件事非常快,所以你需要添加自己的收尾使其更加堅固。

public class ElapsedEventReceiver : ISynchronizeInvoke 
{ 
    private Thread m_Thread; 
    private BlockingCollection<Message> m_Queue = new BlockingCollection<Message>(); 

    public ElapsedEventReceiver() 
    { 
     m_Thread = new Thread(Run); 
     m_Thread.Priority = ThreadPriority.BelowNormal; 
     m_Thread.IsBackground = true; 
     m_Thread.Start(); 
    } 

    private void Run() 
    { 
     while (true) 
     { 
      Message message = m_Queue.Take(); 
      message.Return = message.Method.DynamicInvoke(message.Args); 
      message.Finished.Set(); 
     } 
    } 

    public IAsyncResult BeginInvoke(Delegate method, object[] args) 
    { 
     Message message = new Message(); 
     message.Method = method; 
     message.Args = args; 
     m_Queue.Add(message); 
     return message; 
    } 

    public object EndInvoke(IAsyncResult result) 
    { 
     Message message = result as Message; 
     if (message != null) 
     { 
      message.Finished.WaitOne(); 
      return message.Return; 
     } 
     throw new ArgumentException("result"); 
    } 

    public object Invoke(Delegate method, object[] args) 
    { 
     Message message = new Message(); 
     message.Method = method; 
     message.Args = args; 
     m_Queue.Add(message); 
     message.Finished.WaitOne(); 
     return message.Return; 
    } 

    public bool InvokeRequired 
    { 
     get { return Thread.CurrentThread != m_Thread; } 
    } 

    private class Message : IAsyncResult 
    { 
     public Delegate Method; 
     public object[] Args; 
     public object Return; 
     public object State; 
     public ManualResetEvent Finished = new ManualResetEvent(false); 

     public object AsyncState 
     { 
      get { return State; } 
     } 

     public WaitHandle AsyncWaitHandle 
     { 
      get { return Finished; } 
     } 

     public bool CompletedSynchronously 
     { 
      get { return false; } 
     } 

     public bool IsCompleted 
     { 
      get { return Finished.WaitOne(0); } 
     } 
    } 
} 
+0

這個答案假定沒有尋址的一條重要信息是,在Windows上,只要更高優先級的線程可以運行(通常),較低優先級的線程就不會被調度運行。這意味着設置線程的priorty將實現你想要的。這個事實可能並不明顯,因爲有些人可能認爲priorty只調整時間片或其他方案的大小。請注意,如果Windows沒有運行一段時間,Windows將避免「餓死」低優先級的線程,但聽起來不像是一個問題。 – 2010-07-22 20:58:21

+0

@傑弗裏:好點。事實上,在我當前的例子中,實際上可能會產生問題,因爲編組的消息可能會開始堆疊,可能會使隊列溢出。當我有機會時,我會努力修改這個。 – 2010-07-22 21:07:35

1

也許最簡單的方法是將有一個「忙」標誌(或計數),而忽略只要它是非零的計時器滴答聲。

P.S.不建議更改線程優先級。這幾乎沒有必要。

+0

我想要做的是確保我的應用程序不會影響服務器上的其他應用程序。我在寫一個分析應用程序。 – 2010-07-22 20:50:14

+1

更改其他應用程序的線程優先級可能是個問題,但降低您自己的應用程序的優先級幾乎不會有害。 @邁克爾Hedgpeth - 但一個分析應用程序可能是一個反例! – 2010-07-22 21:21:21

+0

@傑弗裏:我不同意。線程的正確優先級與直觀相反,並且隨着Windows調度程序內置的動態優先級提升,手動調整線程優先級往往適得其反。 – 2010-07-22 23:58:09