Executing multiple Quartz.NET jobs with Topshelf
Asked Answered
B

1

6

I am attempting to run multiple jobs with Quartz.NET and Topshelf using C#.

HostFactory.Run(c =>
{
    c.ScheduleQuartzJobAsService(q =>
        q.WithJob(() => JobBuilder.Create<TypeA>().Build())
        .AddTrigger(() => TriggerBuilder.Create().WithSimpleSchedule(builder => builder.WithIntervalInSeconds(ConfigurationSettings.AppFrequencyInSeconds).RepeatForever()).Build())
        ).StartAutomatically().
        ScheduleQuartzJobAsService(r => 
        r.WithJob(() => JobBuilder.Create<TypeB>().Build())
        .AddTrigger(() => TriggerBuilder.Create().WithSimpleSchedule(builder => builder.
            WithIntervalInSeconds(ConfigurationSettings.AppFrequencyInSeconds).RepeatForever()).Build())
            ).StartAutomatically();
    c.StartAutomatically();
    c.SetServiceName("ServiceName");
});

Using the above code, only the execute method in TypeB gets executed. I have also tried:

HostFactory.Run(c =>
{
    c.ScheduleQuartzJobAsService(q =>
        q.WithJob(() => JobBuilder.Create<TypeA>().Build())
        .AddTrigger(() => TriggerBuilder.Create().WithSimpleSchedule(builder => builder.
            WithIntervalInSeconds(ConfigurationSettings.AppFrequencyInSeconds).RepeatForever()).Build())
        ).StartAutomatically();
    c.StartAutomatically();
    c.SetServiceName("Service1");

    c.ScheduleQuartzJobAsService(r =>
        r.WithJob(() => JobBuilder.Create<TypeB>().Build())
        .AddTrigger(() => TriggerBuilder.Create().WithSimpleSchedule(builder => builder.
            WithIntervalInSeconds(ConfigurationSettings.AppFrequencyInSeconds).RepeatForever()).Build())
        ).StartAutomatically();
    c.StartAutomatically();
    c.SetServiceName("Service2");
});

With this code, only the execute method in TypeB is called. Both my classes TypeA and TypeB have 'Execute' methods which are the entry points for each class (which do get called if they are part of a job on their own). It seems that whichever service code is second is the one that is always called - if I swap the order of these two ScheduleQuartzJobAsService calls it is always the class in the second call that is executed.

How can I write my HostFactory.Run method so both jobs are executed concurrently?

Bible answered 14/8, 2014 at 3:38 Comment(1)
I've discovered that the second method will never work, as "You can only have ONE service! As of 3.x Topshelf the base product no longer support hosting multiple services.". Therefore I think I what I need to know is how to run multiple jobs in the one service.Bible
B
14
HostFactory.Run(c =>
                {
                    c.Service<ContainerService>(s =>
                    {
                        s.ConstructUsing(name => new ContainerService());
                        s.WhenStarted((service, control) => service.Start());
                        s.WhenStopped((service, control) => service.Stop());

                        s.ScheduleQuartzJob<ContainerService>(q =>
                            q.WithJob(() =>
                                JobBuilder.Create<TypeA>().Build())
                            .AddTrigger(() =>
                                TriggerBuilder.Create()
                                    .WithSimpleSchedule(builder => builder
                                        .WithIntervalInSeconds(20)
                                        .RepeatForever())
                                    .Build())
                            );

                        s.ScheduleQuartzJob<ContainerService>(q =>
                            q.WithJob(() =>
                                JobBuilder.Create<TypeB>().Build())
                            .AddTrigger(() =>
                                TriggerBuilder.Create()
                                    .WithSimpleSchedule(builder => builder
                                        .WithIntervalInSeconds(60)
                                        .RepeatForever())
                                    .Build())
                            );
                    });

                });

...

public class ContainerService
{
    public bool Start()
    {
        return true;
    }

    public bool Stop()
    {
        return true;
    }
}

My problem was I was mixing up the concepts of the service and job classes. As soon as I introduced my ContainerService with Start() and Stop() bool methods that returned true, and I called ScheduleQuartzJob rather than ScheduleQuartzJobAsService the above code worked for me as my TypeA and TypeB already implemented IJob.

Bible answered 15/8, 2014 at 5:32 Comment(3)
Can you update this to show your ContainerService?Tecu
If you then install your application as a service in windows, wouldn't this mean that a call to stop the service doesn't actually stop it?Balsa
I have a few question actually. If someone can answer these, big thanks! 1. Is there some kind of Cancellation on the jobs if service shuts down or crashes? 2. I'm planning to implement a lot of jobs in one service, is it a good idea to redesign anything or is it fine to put all job definitions using ScheduleQuartzJob below each other?Hargeisa

© 2022 - 2024 — McMap. All rights reserved.