How does an expired timer event compete with high priority threads?

I have a System.Timers.Timer object that I want to use, but I do not want the timer related processing to interfere with normal high-priority threads. In other words, I would like to say that I want to process X every 5 seconds until nothing works.

How can I guarantee that my timer operations are performed with low priority?

+3
source share
2 answers

The best part about System.Timers.Timer is that you can assign a synchronization object using a property SynchronizingObject, and then use it to trigger a Elapsedstream event , the priority of which can be controlled.

Just assign an instance ElapsedEventReceiverto SynchronizingObjectyour timer property .

Disclaimer: I quickly whipped it, so you need to add your own touches to make it more reliable.

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); }
        }
    }
}
+2
source

Probably the easiest way would be to have a “busy” flag (or count) and ignore the timer until it is zero.

PS Changing thread priorities is not recommended. It is almost never needed.

+1
source

Source: https://habr.com/ru/post/1756039/


All Articles