Is it a good practice using System.Timers.Timer for this case instead of Quartz? [duplicate] - c#

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 days ago.
This post was edited and submitted for review 4 days ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
I need to execute a method, which does some calculations every N ms. Two approaches came to my mind, using Quartz and simple System.Timers.Timer.
Is it a good practice using System.Timers.Timer for this case?
1. Quartz:
var factory = new StdSchedulerFactory();
var scheduler = factory.GetScheduler().Result;
await Task.Run(async () =>
{
var jobDetail = JobBuilder.Create<Calculator>()
.WithIdentity("calc")
.Build();
var trigger = TriggerBuilder.Create()
.WithIdentity("trig")
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(1)
.RepeatForever())
.StartAt(myTimeToStartFiring)
.Build();
await scheduler.ScheduleJob(jobDetail, trigger);
await scheduler.Start();
});
2. System.Timers.Timer
var timer = new Timer();
timer.Interval = 1000;
timer.Elapsed += delegate
{
new Calculator().ExecuteSecond();
};
timer.AutoReset = true;
timer.Enabled = true;
Calculator class
public class Calculator : IJob
{
public async Task Execute(IJobExecutionContext context)
{
//Do some calc
}
public async Task ExecuteSecond()
{
//Do some calc
}
}

Related

I want to create an Email Schedular using Quartz.net [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 months ago.
Improve this question
Can anyone help me a create an email schedular that sends emails every 15 min using quartz in asp.net core?
I found this blog useful when implementing a simple scheduler using quartz.
You can use cronmaker.com to generate the cron expressions you require.
The following string will schedule a job every 15 minutes "0 0/15 * 1/1 * ? *".
To implement the Quartz scheduler first add Quartz to your Program Class.
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddQuartz(q =>
{
q.UseMicrosoftDependencyInjectionJobFactory();
// Create a "key" for the job
var jobKey = new JobKey("EmailJob");
// Register the job with the DI container
q.AddJob<EmailJob>(opts => opts.WithIdentity(jobKey));
// Create a trigger for the job
q.AddTrigger(opts => opts
.ForJob(jobKey) // link to the EmailJob
.WithIdentity("EmailJob-trigger") // give the trigger a unique name
.WithCronSchedule("0 0/15 * 1/1 * ? *")); // run every 15 Minutes
});
services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);
});
}
Next you will need to create a job class which implements IJob from the Quartz library.
[DisallowConcurrentExecution] //Add this so jobs are not scheduled more than once at a time
public class EmailJob : IJob
{
public Task Execute(IJobExecutionContext context)
{
//TODO:: Add email implementation Here
return Task.CompletedTask;
}
}
You can use the blog I mentioned above to allow you to easier register jobs and put your cron job configuration inside your config file.
One note on the blog is to not use "MicrosoftDependencyInjectionScopedJobFactory" and rather use "UseMicrosoftDependencyInjectionJobFactory" as all jobs in Quartz are now scoped.

Best way to time events in Visual Studio? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
In Visual Studio, I am contantly wondering how long code takes to execute. Normally I do this:
var timer = new Stopwatch();
// run some code
timer.Start();
timer.Stop();
Is there an option to do this the same way that breakpoints work in visual studio? I get that this might not be possible because multiple threads, but it would even two aditional breakpoints that acted as A timer start / stop would be cool either in vs or by extension.
Does this exist?
Diagnostics Tools - Events let you see how long each section of code took to run:
An alternative to using breakpoint is to write a static timer method and output it to your logger of choice?
i came up with the following for a project of mine that outputs to Serilog. but you can adapt it to just Console.WriteLine() if you dont have a logger.
public static Task LogExecutionTime(string? detail, Action action)
{
if (!Log.IsEnabled(Serilog.Events.LogEventLevel.Debug))
{
action.Invoke();
return Task.CompletedTask;
}
var stackTrace = new StackTrace();
var methodName = stackTrace.GetFrame(1).GetMethod().Name;
var watch = Stopwatch.StartNew();
action.Invoke();
watch.Stop();
var detailStr = detail is null ? string.Empty : "." + detail;
Log.Logger.Debug($"{methodName}{detailStr}: {watch.ElapsedMilliseconds}ms");
return Task.CompletedTask;
}
example usage
LogExecutionTime("Detail", () =>
{
// your code here
}
Edit to more generic implementation
public static Task LogExecutionTime(Action action)
{
var stackTrace = new StackTrace();
var methodName = stackTrace.GetFrame(1).GetMethod().Name;
var watch = Stopwatch.StartNew();
action.Invoke();
watch.Stop();
Console.WriteLine($"[{DateTime.Now}] {methodName}: {watch.ElapsedMilliseconds}ms");
return Task.CompletedTask;
}
example usage
LogExecutionTime(() =>
{
// your code here
}

how to time limit C# foreach loop to execute an iteration with max time limit [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
how to time limit C# foreach loop, every iteration should run normally and go to next iteration when the previous one take longer than 30sec.
used stopwatch, timer...but those are allowing to run iteration every 30 sec, can anyone help...
Or here you've got an example with Tasks.
foreach(var item in collection)
{
int timeout = 30000;
var task = Task.Run(()=>SomeOperationAsync());
await Task.WhenAny(task, Task.Delay(timeout));
}
Naturally you could also enhance this one with a check if your operation finished before the 30 seconds and so something with a possible result.
You will have to spawn a separate thread for each iteration. But thanks to anonymous delegates you can almost make it appear like code is executed locally.
foreach(var item in collection)
{
var threadItem = item;
ManualResetEvent mre = new ManualResetEvent(false);
Thread workerThread = new Thread( () =>
{
try
{
// do something with threadItem in here
}
finally
{
mre.Set();
}
});
workerThread.Start();
mre.WaitOne(30000); // this will wait for up to 30 sec before proceeding to the next iteration.
}
Just use some thread:
public static void ThreadAbortDemo(int sleeptime)
{
int[] collection = new int[10];
foreach (var item in collection)
{
System.Threading.Thread thread = new System.Threading.Thread(() =>
{
try
{
// do your stuff with item
}
catch (System.Threading.ThreadAbortException)
{
// this thread is disposed by thread.Abort() statement
// do some stuff here before exit this thread
}
});
thread.Start();
System.Threading.Timer timer = new System.Threading.Timer((o) =>
{
try
{
thread.Abort(o);
}
catch
{
// the thread is done before Abort statement called
}
},new object(),sleeptime,System.Threading.Timeout.Infinite);
}
}
the code above just example, you can you another way like task or thread pool to reduce the cost of create a thread.

How can I add timeout to this code [duplicate]

This question already has answers here:
Asynchronously wait for Task<T> to complete with timeout
(19 answers)
Closed 8 years ago.
I am trying to add timeout to this code, but because I am new to this, I can't figure out,
Task.Factory.StartNew(() =>
{
Aspose.Words.Document doc = new Aspose.Words.Document(inputFileName);
doc.Save(Path.ChangeExtension(inputFileName, ".pdf"));
});
Also I want main thread to wait here until it timeout for 5 minutes or completes.
Edit
Or can I use cancellation token with this, if yes then how :( ?
You can create a new Task using Task.Delay and use Task.WhenAny:
Task delayedTask = Task.Delay(TimeSpan.FromMinutes(5));
Task workerTask = Task.Factory.StartNew(() =>
{
Aspose.Words.Document doc = new Aspose.Words.Document(inputFileName);
doc.Save(Path.ChangeExtension(inputFileName, ".pdf"));
});
if (await Task.WhenAny(delayedTask, workerTask) == delayedTask)
{
// We got here because the delay task finished before the workertask.
}
else
{
// We got here because the worker task finished before the delay.
}
You can use Microsoft.Bcl.Async to add async-await abilities to .NET 4.0
Edit:
As you're using VS2010, you can use Task.Factory.ContinueWheAny instead:
Task.Factory.ContinueWhenAny(new[] { delayedTask, workerTask }, task =>
{
if (task == delayedTask)
{
// We got here if the delay task finished before the workertask.
}
else
{
// We got here if the worker task finished before the delay.
}
});
Edit 2:
Since Task.Delay isn't available in .NET 4.0, you can create it yourself using an Extension Method:
public static class TaskExtensions
{
public static Task Delay(this Task task, TimeSpan timeSpan)
{
var tcs = new TaskCompletionSource<bool>();
System.Timers.Timer timer = new System.Timers.Timer();
timer.Elapsed += (obj, args) =>
{
tcs.TrySetResult(true);
};
timer.Interval = timeSpan.Milliseconds;
timer.AutoReset = false;
timer.Start();
return tcs.Task;
}
}

How do I take a Task<T> and put a timeout on it? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
My other question basically needed this so I thought I would share my generic solution here.
I had trouble with HttpClient Tasks for web requests basically never completing; so the program or thread hangs. I needed a simple way to add a timeout to a task, so that it returns normally or returns cancelled if the timeout expires first.
Some alternative approaches can be found here:
http://blogs.msdn.com/b/pfxteam/archive/2011/11/10/10235834.aspx
You technically can't take a task and force it to be canceled after some period of time. The best that you can do is create a new task that will be marked as canceled after the given period of time, or will be completed when the other task is if it finishes in time.
A key point to note is that the operation timing out doesn't stop the task from continuing on with it's work, it just fires off all continuations of this new task "early" if the timeout is reached.
Doing this is pretty trivial, thanks to the use of CancellationToken:
var newTask = task.ContinueWith(t => { }
, new CancellationTokenSource(timeoutTime).Token);
We can combine this patter with WhenAny to easily ensure that any exceptions are properly propagated through to the continuation. A copy for tasks with/without a result is also needed:
public static Task WithTimeout(Task task, TimeSpan timeout)
{
var delay = task.ContinueWith(t => { }
, new CancellationTokenSource(timeout).Token);
return Task.WhenAny(task, delay).Unwrap();
}
public static Task<T> WithTimeout<T>(Task<T> task, TimeSpan timeout)
{
var delay = task.ContinueWith(t => t.Result
, new CancellationTokenSource(timeout).Token);
return Task.WhenAny(task, delay).Unwrap();
}
You can use CancellationTokenSource when the timeout come:
var DefualtTimeout = 5000;
var cancelToken = new CancellationTokenSource();
var taskWithTimeOut = Task.Factory.StartNew( t =>
{
var token = (CancellationToken)t;
while (!token.IsCancellationRequested)
{
// Here your work
}
token.ThrowIfCancellationRequested();
}, cancelToken.Token, cancelToken.Token);
Approach 1:
if (!taskWithTimeOut.Wait(DefualtTimeout, cancelToken.Token))
{
cancelToken.Cancel();
}
Approach 2:
SpinWait.SpinUntil(() => taskWithTimeOut.IsCompleted, new TimeSpan(0, 0, 0, 0, DefualtTimeout ));
Approach 3:
You can make the method async and before the task write await taskWithTimeOut.Wait.. in this way the UI will not blocked.

Categories