2010-07-22 63 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