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