windows 服务中的另一个进程正在使用文件

File being used by another process in windows service

我编写了以下运行良好的代码,但问题是有时它会给我 file being used by another process 这两个作业正在访问和写入同一个文件。 ClickProfileJob 首先运行并在 5 秒后重复,然后根据 5 秒的计划运行第二个作业 ClickLikeJob。我见过几个解决方案,它们建议使用我在下面编码的相同 using 技术。

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

这不是 Quartz 特有的问题。您可以使用 SemaphoreSlim 或更好的简单 lock。只需创建一个基础工作并从中派生其他工作。然后在两个Jobs中锁定LockObject

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