Search code examples
c#filequartz.nettopshelf

File being used by another process in windows service


I have written following code which runs fine but problem is that sometimes it gives me file being used by another process these two jobs are accessing and writing the same file. ClickProfileJob runs first and repeats after 5 seconds and then the second job ClickLikeJob according to schedule of 5 seconds. I have seen couple of solutions which had suggested the same usingtechnique which I have coded below.

    using Quartz;
    using System;
    using System.IO;
    using Topshelf;
    using Topshelf.Quartz;

    namespace FinyaConsole
    {
     class Program
     {
        static void Main(string[] args)
        {
            userCreds creds = new userCreds();

            if (creds.checkUser().Length > 3)
            {
                HostFactory.Run(x =>
                {
                    x.Service<GiveHeartsService>(s =>
                    {
                        s.WhenStarted(service => service.OnStart());
                        s.WhenStopped(service => service.OnStop());
                        s.ConstructUsing(() => new GiveHeartsService());

                        s.ScheduleQuartzJob(q =>
                            q.WithJob(() =>
                                JobBuilder.Create<ClickProfileJob>().Build())
                                .AddTrigger(() => TriggerBuilder.Create()
                                    .WithSimpleSchedule(b => b
                                        .WithIntervalInSeconds(5)
                                        .RepeatForever())
                                    .Build()));

                        s.ScheduleQuartzJob(q =>
                            q.WithJob(() =>
                                JobBuilder.Create<ClickLikeJob>().Build())
                                .AddTrigger(() => TriggerBuilder.Create()
                                    .WithSimpleSchedule(b => b
                                        .WithIntervalInSeconds(5)
                                        .RepeatForever())
                                    .Build()));


                    });

                    //.DependsOnEventLog()

                    x.RunAsLocalSystem()
                        .StartAutomaticallyDelayed()
                        .EnableServiceRecovery(rc => rc.RestartService(1));

                    x.SetServiceName("FinyaHearts");
                    x.SetDisplayName("FinyaHearts");
                    x.SetDescription("This is a service.");
                });
            }
        }
    }
        public class ClickProfileJob : IJob
        {
            public void Execute(IJobExecutionContext context)
            {
                try
                {
                    using (StreamWriter sw = new StreamWriter(".\\visits_to_others.txt", true))
                    {

                        //Write a line of text
                        sw.WriteLine($"[{DateTime.Now}] Welcome from ClickProfileJob!");
                        Console.WriteLine($"[{DateTime.Now}] Welcome from ClickProfileJob!");
                        //System.IO.File.WriteAllText(@"path\visit_users.txt", userLink);
                        //Close the file
                        sw.Flush();
                        sw.Dispose();
                        sw.Close();
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("Exception: " + e.Message);
                }
                finally
                {
                    //Console.WriteLine("Executing finally block.");
                }
            }
        }

        public class ClickLikeJob : IJob
        {
            public void Execute(IJobExecutionContext context)
            {
                try
                {
                    using (StreamWriter sw = new StreamWriter(".\\visits_to_others.txt", true))
                    {

                        //Write a line of text
                        sw.WriteLine($"[{DateTime.Now}] Welcome from ClickLikeJob!");
                        Console.WriteLine($"[{DateTime.Now}] Welcome from ClickLikeJob!");
                        //System.IO.File.WriteAllText(@"path\visit_users.txt", userLink);
                        //Close the file
                        sw.Flush();
                        sw.Dispose();
                        sw.Close();
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("Exception: " + e.Message);
                }
                finally
                {
                    //Console.WriteLine("Executing finally block.");
                }
            }
        }
    }

Solution

  • This is not a Quartz specific problem. You can use a SemaphoreSlim or better a simple lock. Just create a base job and derive your other Jobs from it. Then lock the LockObject in both Jobs.

    public abstract class LockableJobBase
    {
        protected static object LockObject = new object();
    }
    
    
    public class ClickProfileJob : LockableJobBase, IJob
    {
        public void Execute(IJobExecutionContext context)
        {
            try
            {
                lock (LockObject)
                {
                    using (StreamWriter sw = new StreamWriter(".\\visits_to_others.txt", true))
                    {
                        // your sw stuff
                    }
                }
    
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception: " + e.Message);
            }
            finally
            {
                //Console.WriteLine("Executing finally block.");
            }
        }
    }
    
    public class ClickLikeJob : LockableJobBase, IJob
    {
        public void Execute(IJobExecutionContext context)
        {
            try
            {
                lock (LockObject)
                {
                    using (StreamWriter sw = new StreamWriter(".\\visits_to_others.txt", true))
                    {
                        // your sw stuff
                    }
                }
    
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception: " + e.Message);
            }
            finally
            {
                //Console.WriteLine("Executing finally block.");
            }
        }
    }