计时器已用事件如何与高优先级线程竞争?

发布于 2024-09-11 08:20:33 字数 139 浏览 1 评论 0原文

我有一个想要使用的 System.Timers.Timer 对象,但我不希望与 Timer 相关的处理干扰正常到高优先级的线程。换句话说,我想说的是,只要没有其他东西在运行,我希望每 5 秒处理一次 X。

如何确保我的计时器操作以低优先级方式运行?

I have a System.Timers.Timer object that I want to use, but I don't want the processing tied to the Timer to interfere with normal to high priority threads. In other words, I'd like to say that I want to process X every 5 seconds as long as nothing else is running.

How could I ensure that my Timer operations are running in a low-priority manner?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

驱逐舰岛风号 2024-09-18 08:20:33

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); }
        }
    }
}

The nice thing about System.Timers.Timer is that you can assign a synchronzing object via the SynchronizingObject property and then exploit it to run the Elapsed event a thread whose priority can be controlled.

Just assign an instance of the ElapsedEventReceiver to the SynchronizingObject property of your timer.

Disclaimer: I whipped this up pretty fast so you will need to add your own finishing touches to make it more robust.

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); }
        }
    }
}
我们的影子 2024-09-18 08:20:33

也许最简单的方法是有一个“忙”标志(或计数),并忽略计时器滴答声,只要它不为零。

PS 不建议更改线程优先级。几乎没有必要。

Probably the easiest way would be to have a "busy" flag (or count), and ignore the timer ticks as long as it's non-zero.

P.S. Changing thread priorities is not recommended. It's hardly ever necessary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文