C# 以不同间隔运行的并行循环

C# 以不同间隔运行的并行循环,c#,multithreading,parallel-processing,C#,Multithreading,Parallel Processing,在C语言中,我试图创建一个包含两个循环的Windows服务,这两个循环将以设定的间隔同时运行。例如,LoopA每30秒运行一次,LoopB每5秒运行一次 在LoopA内部执行的任务可能需要30秒以上才能完成。如果发生这种情况,LoopA将立即重新开始,就像任务只需要20秒一样,LoopA在10秒内不会再次运行 我已经实现了LoopA。我现在的问题是实现LoopB以并行方式运行,其行为方式与LoopA相同,只是间隔5秒。这是我的LoopA代码,它在线程中运行: private Thread Wor

在C语言中,我试图创建一个包含两个循环的Windows服务,这两个循环将以设定的间隔同时运行。例如,LoopA每30秒运行一次,LoopB每5秒运行一次

在LoopA内部执行的任务可能需要30秒以上才能完成。如果发生这种情况,LoopA将立即重新开始,就像任务只需要20秒一样,LoopA在10秒内不会再次运行

我已经实现了LoopA。我现在的问题是实现LoopB以并行方式运行,其行为方式与LoopA相同,只是间隔5秒。这是我的LoopA代码,它在线程中运行:

private Thread Worker;
private AutoResetEvent StopRequest;

private TimeSpan loop_a_freq;
private TimeSpan loob_b_freq;

public LoopManager(Thread _worker, AutoResetEvent _stopRequest)
{
    // Threads
    this.Worker = _worker;
    this.StopRequest = _stopRequest;

    RunLoopA();
}

private void RunLoopA()
{
    DateTime start_current_loop = DateTime.Now;
    DateTime next_loop = start_current_loop + loop_a_freq;

    for (;;)
    {
        // Do processing here
        new LoopAction();

        DateTime now = DateTime.Now;
        if (now > next_loop)
        {
            next_loop = now;
        }

        TimeSpan delay = next_loop - now;
        Thread.Sleep(delay);

        next_loop += loop_a_freq;

        if (StopRequest.WaitOne(0))
        {
            return;
        }
    }
}

我如何实现RunLoopB?线程是C的一个方面,我从来没有充分探讨过。我是否需要使用Parallel.For?

这里有一个小片段,您可以将其放入linqpad并使用它进行测试。这将防止计时器重叠。基本上,我们执行回调,停止计时器,处理一些工作,重置计时器并再次启动它。每个定时任务都需要一个计时器

要明确的是,这将防止线程不必要地排队,因为只有在另一个线程完成后才创建一个新线程来处理工作。拥有2个计时器将允许您以不同的时间间隔运行2个不同的进程,创建它们自己的线程。同样,每个计时器只允许每个进程发生一个实例

基本过程

构造函数中没有间隔的设置计时器 启动计时器 计时器等待,然后在新线程上启动进程 进程停止计时器 这个过程确实有效 进程根据自动重置属性设置重置计时器的间隔 进程启动计时器 重复步骤3 基本代码

故障排除性能

此外,我昨天发现了这篇文章,它可能有助于您诊断线程性能


下面是一个小片段,您可以将其放入linqpad中并使用它进行测试。这将防止计时器重叠。基本上,我们执行回调,停止计时器,处理一些工作,重置计时器并再次启动它。每个定时任务都需要一个计时器

要明确的是,这将防止线程不必要地排队,因为只有在另一个线程完成后才创建一个新线程来处理工作。拥有2个计时器将允许您以不同的时间间隔运行2个不同的进程,创建它们自己的线程。同样,每个计时器只允许每个进程发生一个实例

基本过程

构造函数中没有间隔的设置计时器 启动计时器 计时器等待,然后在新线程上启动进程 进程停止计时器 这个过程确实有效 进程根据自动重置属性设置重置计时器的间隔 进程启动计时器 重复步骤3 基本代码

故障排除性能

此外,我昨天发现了这篇文章,它可能有助于您诊断线程性能


这似乎已经完全准备就绪,但为了让另一个线程运行,您需要并行启动第一个线程,第二个线程也是如此,然后等待它们。这可能比使用线程更容易,但这里使用的是线程


现在,如果您希望能够确保每个循环在不等待前一个过程完成的情况下启动,那么您将开始研究一个由服务提供更好服务的实现。请注意,在这种情况下,您不想使用System.Threading.Timer,因为它缺少事件模式。

这似乎已经完全准备就绪,但为了让另一个线程运行,您需要并行启动第一个线程,第二个线程也一样,然后等待它们。这可能比使用线程更容易,但这里使用的是线程

        using System.Timers;

        enum EventType {quit, task};

        class LoopDaLoop {

            Timer _30Seconds_publiser = new Timer(20000);
            Timer _5Seconds_publisher = new Timer(5000);

            Timer _terminator = new Timer(60000);

            BlockingCollection<EventType> loopAEvents = new BlockingCollection<EventType>();
            BlockingCollection<EventType> loopBEvents = new BlockingCollection<EventType>();

            public LoopDaLoop() {
                _30Seconds_publiser.Elapsed += _30Seconds_publiser_Elapsed;
                _5Seconds_publisher.Elapsed += _5Seconds_publisher_Elapsed;
                _terminator.Elapsed += _terminator_Elapsed;
                _30Seconds_publiser.Start();
                _5Seconds_publisher.Start();
                _terminator.Start();

                Task.Run(() => loopA());
                Task.Run(() => loopB());
            }

            void _terminator_Elapsed(object sender, ElapsedEventArgs e) {
                loopAEvents.Add(EventType.quit);
                loopBEvents.Add(EventType.quit);
            }

            void _5Seconds_publisher_Elapsed(object sender, ElapsedEventArgs e) {
                loopBEvents.Add(EventType.task);
            }

            void _30Seconds_publiser_Elapsed(object sender, ElapsedEventArgs e) {
                loopAEvents.Add(EventType.task);
            }


            private void loopA() {
                while (loopAEvents.Take() != EventType.quit) {
                    // decrypt wife's personal email
                }
            }

            private void loopB() {
                while (loopBEvents.Take() != EventType.quit) {
                    // navigate attack drones
                }
            }
        }

现在,如果您希望能够确保每个循环在不等待前一个过程完成的情况下启动,那么您将开始研究一个由服务提供更好服务的实现。请注意,在这种情况下,您不想使用System.Threading.Timer,因为它缺少事件模式。

您是否想过使用计时器来安排任务。你可以在给定的时间间隔内启动线程,而不是让无限循环休眠。我是这样做的,但计时器无法正确处理超出时间间隔的任务,因此如果30秒的任务实际上需要40秒。从那以后,我的设计规范发生了变化,因此它可能值得研究。一个计时器将每隔给定的时间间隔触发一个新线程,即使前一个线程尚未完成。但是,没有什么可以阻止您在工作任务开始时检查变量,以查看是否已经有任务正在运行,如果已经有任务,则直接返回而不执行任何操作。计时器是否允许我以不同的间隔启动两个不同的线程并使它们并行运行?是的,您只有两个不同的计时器和两个线程D
        using System.Timers;

        enum EventType {quit, task};

        class LoopDaLoop {

            Timer _30Seconds_publiser = new Timer(20000);
            Timer _5Seconds_publisher = new Timer(5000);

            Timer _terminator = new Timer(60000);

            BlockingCollection<EventType> loopAEvents = new BlockingCollection<EventType>();
            BlockingCollection<EventType> loopBEvents = new BlockingCollection<EventType>();

            public LoopDaLoop() {
                _30Seconds_publiser.Elapsed += _30Seconds_publiser_Elapsed;
                _5Seconds_publisher.Elapsed += _5Seconds_publisher_Elapsed;
                _terminator.Elapsed += _terminator_Elapsed;
                _30Seconds_publiser.Start();
                _5Seconds_publisher.Start();
                _terminator.Start();

                Task.Run(() => loopA());
                Task.Run(() => loopB());
            }

            void _terminator_Elapsed(object sender, ElapsedEventArgs e) {
                loopAEvents.Add(EventType.quit);
                loopBEvents.Add(EventType.quit);
            }

            void _5Seconds_publisher_Elapsed(object sender, ElapsedEventArgs e) {
                loopBEvents.Add(EventType.task);
            }

            void _30Seconds_publiser_Elapsed(object sender, ElapsedEventArgs e) {
                loopAEvents.Add(EventType.task);
            }


            private void loopA() {
                while (loopAEvents.Take() != EventType.quit) {
                    // decrypt wife's personal email
                }
            }

            private void loopB() {
                while (loopBEvents.Take() != EventType.quit) {
                    // navigate attack drones
                }
            }
        }


不同的时间间隔。你有没有想过用定时器来安排你的任务。你可以在给定的时间间隔内启动线程,而不是让无限循环休眠。我是这样做的,但计时器无法正确处理超出时间间隔的任务,因此如果30秒的任务实际上需要40秒。从那以后,我的设计规范发生了变化,因此它可能值得研究。一个计时器将每隔给定的时间间隔触发一个新线程,即使前一个线程尚未完成。但是,没有什么可以阻止您在工作任务开始时检查变量,以查看是否已经有任务正在运行,如果已经有任务,则直接返回而不执行任何操作。计时器是否允许我以不同的间隔启动两个不同的线程并使它们并行运行?是的,您只有两个不同的计时器和两个线程不同的时间间隔。非常感谢。你能简单地阐述一下你所说的“线程重叠”是什么意思吗?如果两个计时器并排运行,那么重叠的部分会是什么?当然,您将并行运行两个计时器,并旋转各自的线程,这样该部分就可以正常工作。此设置可防止ProcessA在仍在处理时再次执行。它之所以这样做是因为ProcessA停止计时器,进行工作,然后再次启动计时器。所以基本上ProcessA一次只运行一个实例。因此,换句话说,ProcessA和ProcessB都可以运行,但使用上述设置只能运行其中一个的一个实例。如果这还不清楚,我可以换个说法。你是老板,托尼。谢谢你的帮助。谢谢,是的,我也是线程新手,刚刚经历了所有这些lol。很高兴我能把它传下去:非常感谢。你能简单地阐述一下你所说的“线程重叠”是什么意思吗?如果两个计时器并排运行,那么重叠的部分会是什么?当然,您将并行运行两个计时器,并旋转各自的线程,这样该部分就可以正常工作。此设置可防止ProcessA在仍在处理时再次执行。它之所以这样做是因为ProcessA停止计时器,进行工作,然后再次启动计时器。所以基本上ProcessA一次只运行一个实例。因此,换句话说,ProcessA和ProcessB都可以运行,但使用上述设置只能运行其中一个的一个实例。如果这还不清楚,我可以换个说法。你是老板,托尼。谢谢你的帮助。谢谢,是的,我也是线程新手,刚刚经历了所有这些lol。很高兴我能把它传下去:谢谢你的回答。如果我可以点击接受多个答案,我会的!谢谢你的回答。如果我可以点击接受多个答案,我会的!
        using System.Timers;

        enum EventType {quit, task};

        class LoopDaLoop {

            Timer _30Seconds_publiser = new Timer(20000);
            Timer _5Seconds_publisher = new Timer(5000);

            Timer _terminator = new Timer(60000);

            BlockingCollection<EventType> loopAEvents = new BlockingCollection<EventType>();
            BlockingCollection<EventType> loopBEvents = new BlockingCollection<EventType>();

            public LoopDaLoop() {
                _30Seconds_publiser.Elapsed += _30Seconds_publiser_Elapsed;
                _5Seconds_publisher.Elapsed += _5Seconds_publisher_Elapsed;
                _terminator.Elapsed += _terminator_Elapsed;
                _30Seconds_publiser.Start();
                _5Seconds_publisher.Start();
                _terminator.Start();

                Task.Run(() => loopA());
                Task.Run(() => loopB());
            }

            void _terminator_Elapsed(object sender, ElapsedEventArgs e) {
                loopAEvents.Add(EventType.quit);
                loopBEvents.Add(EventType.quit);
            }

            void _5Seconds_publisher_Elapsed(object sender, ElapsedEventArgs e) {
                loopBEvents.Add(EventType.task);
            }

            void _30Seconds_publiser_Elapsed(object sender, ElapsedEventArgs e) {
                loopAEvents.Add(EventType.task);
            }


            private void loopA() {
                while (loopAEvents.Take() != EventType.quit) {
                    // decrypt wife's personal email
                }
            }

            private void loopB() {
                while (loopBEvents.Take() != EventType.quit) {
                    // navigate attack drones
                }
            }
        }