Execute function every 5 minutes in background - c#

I have function which reads Data out of an Webservice. With that Data i create Bitmaps. I send the Bitmaps to Panels (Displays) which displays the created Bitmaps. Manually its working like charm. What i need now is, that my Application run this function every 5 min automtically in the Backround.
My Application is running under IIS. How can i do that? Can someone help me with that?

You don't have to be depended on asp.net project, but you can use Cache Callback to do it.
I have found a nice approach, to do it.
actually i don't remember the link so i'll give you a code that i use:
public abstract class Job
{
protected Job()
{
Run();
}
protected abstract void Execute();
protected abstract TimeSpan Interval { get; }
private void Callback(string key, object value, CacheItemRemovedReason reason)
{
if (reason == CacheItemRemovedReason.Expired)
{
Execute();
Run();
}
}
protected void Run()
{
HttpRuntime.Cache.Add(GetType().ToString(), this, null,
Cache.NoAbsoluteExpiration, Interval, CacheItemPriority.Normal, Callback);
}
}
Here is the implementation
public class EmailJob : Job
{
protected override void Execute()
{
// TODO: send email to whole users that are registered
}
protected override TimeSpan Interval
{
get { return new TimeSpan(0, 10, 0); }
}
}

An Asp.Net application is not the correct framework for a task like this.
You should probably create a dedicated service for this type of tasks.
Another option is to create a scheduled task that will run every X minutes
On a side note, if you must do this through your asp.net application, I recommend reading on how to Simulate a Windows Service using ASP.NET to run scheduled jobs

Related

.NET client-side WCF with queued requests

Background
I'm working on updating legacy software library. The legacy code uses an infinitely looping System.Threading.Thread that executes processes in the queue. These processes perform multiple requests with another legacy system that can only process one request at a time.
I'm trying to modernize, but I'm new to WCF services and there may be a big hole in my knowledge that'd simplify things.
WCF Client-Side Host
In modernizing, I'm trying to move to a client-side WCF service. The WCF service allows requests to be queued from multiple a applications. The service takes a request and returns a GUID back so that I can properly associate via the callbacks.
public class SomeService : ISomeService
{
public Guid AddToQueue(Request request)
{
// Code to add the request to a queue, return a Guid, etc.
}
}
public interface ISomeCallback
{
void NotifyExecuting(Guid guid)
void NotifyComplete(Guid guid)
void NotifyFault(Guid guid, byte[] data)
}
WCF Client Process Queues
The problem I'm having is that the legacy processes can include more than one request. Process 1 might do Request X then Request Y, and based on those results follow up with Request Z. With the legacy system, there might be Processes 1-10 queued up.
I have a cludgy model where the process is executed. I'm handling events on the process to know when it's finished or fails. But, it just feels really cludgy...
public class ActionsQueue
{
public IList<Action> PendingActions { get; private set; }
public Action CurrentAction { get; private set; }
public void Add(Action action)
{
PendingAction.Add(action)
if (CurrentAction is null)
ExecuteNextAction();
}
private void ExecuteNextAction()
{
if (PendingActions.Count > 0)
{
CurrentAction = PendingActions[0];
PendingActions.RemoveAt(0);
CurrentAction.Completed += OnActionCompleted;
CurrentAction.Execute();
}
}
private OnActionCompleted(object sender, EventArgs e)
{
CurrentAction = default;
ExecuteNextAction();
}
}
public class Action
{
internal void Execute()
{
// Instantiate the first request
// Add handlers to the first request
// Send it to the service
}
internal void OnRequestXComplete()
{
// Use the data that's come back from the request
// Proceed with future requests
}
}
With the client-side callback the GUID is matched up to the original request, and it raises a related event on the original requests. Again, the implementation here feels really cludgy.
I've seen example of Async methods for the host, having a Task returned, and then using an await on the Task. But, I've also seen recommendations not to do this.
Any recommendations on how to untangle this mess into something more usable are appreciated. Again, it's possible that there's a hole in my knowledge here that's keeping me from a better solutiong.
Thanks
Queued communication between the client and the server of WCF is usually possible using a NetMsmqbinding, which ensures persistent communication between the client and the server. See this article for specific examples.
If you need efficient and fast message processing, use a non-transactional queue and set the ExactlyOnce attribute to False, but this has a security impact. Check this docs for further info.
In case anyone comes along later with a similar issue, this is a rough sketch of what I ended up with:
[ServiceContract(Name="MyService", SessionMode=Session.Required]
public interface IMyServiceContract
{
[OperationContract()]
Task<string> ExecuteRequestAsync(Action action);
}
public class MyService: IMyServiceContract
{
private TaskQueue queue = new TaskQueue();
public async Task<string> ExecuteRequestAsync(Request request)
{
return await queue.Enqueue(() => request.Execute());
}
}
public class TaskQueue
{
private SemaphoreSlim semaphore;
public TaskQueue()
{
semaphore = new SemaphoreSlim(1);
}
Task<T> Enqueue<T>(Func<T> function)
{
await semaphore.WaitAsync();
try
{
return await Task.Factory.StartNew(() => function.invoke();)
}
finally
{
semaphore.Release();
}
}
}

Call Function After a specific intervel

I'm trying to call a function at a regular interval.
The code below is written in the global.asax.cs file and it's working is ScheduleTaskTrigger() calls CheckLicenseExpiry() after 1 min. But I also want to call this function every , let's say 4 hrs.
is there anyway for achieving this by changing this code:
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
//used here formating API//
HttpConfiguration config = GlobalConfiguration.Configuration;
config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
ScheduleTaskTrigger();
}
static void ScheduleTaskTrigger()
{
HttpRuntime.Cache.Add("ScheduledTaskTrigger",
string.Empty,
null,
Cache.NoAbsoluteExpiration,
// TimeSpan.FromMinutes(60), // Every 1 hour
// TimeSpan.FromMinutes(0.0167),
TimeSpan.FromMinutes(1),
CacheItemPriority.NotRemovable,
new CacheItemRemovedCallback(CheckLicenseExpiry));
}
static void CheckLicenseExpiry(string key, Object value, CacheItemRemovedReason reason)
{
CompanyHelper.CheckLicenseExpired();
}
If you're willing to use Windows Forms, use the "Timer" class.
using System.Windows.Forms;
//[...]
Timer timer;
private void Initialiser()
{
Timer timer = new Timer();
timer.Interval = 3600000;//Set interval to an hour in the form of milliseconds.
timer.Tick += new EventHandler(timer_Tick);
}
private void timer_Tick(object sender, EventArgs e)
{
//The function you wish to do every hour.
}
You can change the interval to anything given that it is in the form of milliseconds (1000 per second). (e.g. 1 minute: 60000, 4 hours: 14400000).
P.S You can just use the "System.Windows.Forms" library without necessarily having a Windows Forms program, I imagine you could use this code in WPF also).
Please use the System.Threading.Timer(MSDN link). It provides a mechanism for executing a method at specified intervals and does not depends on platform:
new System.Threading.Timer(_ =>
{
// do something here
},
null,
TimeSpan.FromMinutes(1) /*dueTime*/,
TimeSpan.FromHours(1) /*period*/
);
I recommend using Quartz.Net.
Global.asax
public class Global : System.Web.HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
Scheduler.Start();
}
void Application_End(object sender, EventArgs e)
{
Scheduler.Stop();
}
}
Scheduler.cs (helper class)
using Quartz;
using Quartz.Impl;
public class Scheduler
{
private static IScheduler _scheduler;
public static void Start()
{
_scheduler = StdSchedulerFactory.GetDefaultScheduler();
_scheduler.Start();
ITrigger myTrigger = TriggerBuilder.Create()
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInHours(4)
.RepeatForever())
.Build();
IJobDetail myJob = JobBuilder.Create<MyJobClass>().Build();
_scheduler.ScheduleJob(myJob, myTrigger);
}
public static void Stop()
{
if (_scheduler != null)
{
_scheduler.Shutdown();
}
}
}
MyJobClass.cs
[DisallowConcurrentExecution]
public class MyJobClass : IJob
{
public void Execute(IJobExecutionContext context)
{
//do something
}
}
I hope this helps.
As I read from your sample, you want to check whether a license has expired on a regular basis. Solving this using the ASP.NET cache - which might work but maybe not in all scenarios (ASP.NET cache was built for a different purpose). Also, using timers is not a good idea as the application pool of the web application might not be running thus the task will not be executed.
Instead you could check on each request whether the license has expired. In order to save performance, you could only check if the last check was done more than 4 hours ago.
In ASP.NET MVC you can create an ActionFilter or AuthorizationFilter that implements this logic. You can apply this filter either globally to all routes or only to specific routes/controllers/actions.
As you want to block access to your site if the check is not successful, a custom AuthorizationFilter is a good approach. For details on ActionFilters, see this link, for a sample on implementing a custom AuthorizationFilter, see this link.
In the filter, you should be aware that there can be parallel requests that access the variable that stores the time of the last check. So you need to lock the resources in a appropriate way.

Azure Service Charge For A Worker Role

I'm just wondering what would happen if I have a worker roles hosting in Azure, and instead of
public class WorkerRole : RoleEntryPoint
{
public override void Run()
{
while (true)
{
Thread.Sleep(10000);
Trace.TraceInformation("Working", "Information");
}
}
//Other code remove for brevity
}
}
I do
public class WorkerRole : RoleEntryPoint
{
public override void Run()
{
while (true)
{
}
}
//Other code remove for brevity
}
}
I know that the second code snippet spinning the process all the time, which is bad. But is there any other differences in terms of money?
Thanks.
As long as you don't produce network transfer, that second while(true) code would simply block your worker role's main thread if each iteration takes few milliseconds to be processed.
You can check how worker roles are billed using Azure Pricing Calculator for cloud services (and you'll discover that you pay a fixed price per month based on CPU power and RAM, and also based on network bandwidth).

Log EF query time to database

I want to log EF query (or transaction) times back to the database so that I can monitor performance in a live system. Note I know that more than one query can happen within my UOW. That is fine, I just want to be able to tell what areas of the system are slowing down etc.
What is the best way for me to do this? My initial thought was to do this in UnitOfWork.Dispose() so that every query would automatically be logged once completed. But this smells a bit to me because I'd have to call Save() to persist the information, but what if the caller didn't want to save?
Is there another, better way I can automatically log the query time to the database?
protected virtual void Dispose(bool disposing)
{
if (this.logQueryToDatabase)
{
var timeTaken = DateTime.UtcNow - this.start;
LogPerformance(this.callingFnName, timeTaken.TotalMilliseconds);
}
this.ctx.Dispose();
}
If you know which actions to measure you can create a simple class to handle this. All you need is to wrap around the action.
The profiler class.
public class Profiler:IDisposable
{
private readonly string _msg;
private Stopwatch _sw;
public Profiler(string msg)
{
_msg = msg;
_sw = Stopwatch.StartNew();
}
public void Dispose()
{
_sw.Stop();
LogPerformance(_msg, _sw.ElapsedMilliseconds);
}
}
The usage:
using (new Profiler("Saving products"))
{
db.SaveChanges();
}

Update UpdatePanel on different user’s web page

I have a web page (aspx). This page has a button , a UpdatePanel and a Timer. Now my problem is as follow suppose 10 users are on this page at the same time and suppose user number 3 and 8 click its button then all user’s UpdatePanel should get updated. What is right way to achieve this functionality?
Since each user is running its own copy of the web application so whats happenning on one user's browser can't be notified to the other user. One thing you could do is when one user clicks the button to update, you could save it, whereas all the user application could ping the server may be every 2 secs to know if updation happens and if so updates.
You could use a Global property. On that property, you can put an Observer pattern, and let the visitors subscribe. When you alter the Application property ( shared throughout all Sessions ), you call the Notify() method. The client Notify() method gets called, and there you put functionality to update the UpdatePanel.
This code is NOT TESTED, it is a guideline
// *** GLOBAL.ASAX
// This collection will contain all the updatepanels that need to be updated
private List<IUpdatePanelClient> _registeredClients = new List<IUpdatePanelClient>();
public static void RegisterClient(IUpdatePanelClient client)
{
_registeredClients.Add(client);
}
public static void UnregisterClient(IUpdatePanelClient client)
{
_registeredClients.Remove(client);
}
// Which client is triggering the update call ?
private IUpdatePanelClient _clientUpdating = null;
public static IUpdatePanelClient ClientUpdating
{
get { return _clientUpdating ; }
set { _clientUpdating = value; Notify(); }
}
// Notify the clients
public static void Notify()
{
foreach(IUpdatePanelClient client in _registeredClients)
{
client.Update();
}
}
// *** IUPdatePanelClient.CS
interface IUpdatePanelClient // Interface to make the calls
{
void Update();
}
// *** Your codepage
public class MyUpdatePanelPage : Page, IUpdatePanelClient // Inherit the interface
{
public void Page_Load(Object sender, EventArgs e)
{
MyUpdatePanelPage.Global.RegisterClient(this);
}
public void Btn_Click(Object sender, EventArgs e)
{
MyUpdatePanelPage.Global.ClientUpdating = this;
}
public void Update()
{
this._updatePanel1.Update();
}
}
Your question doesn't have enough information for anyone to answer properly. If there is information that you want to keep all users update-to-date on, store that information in a database. When one user edits the data from their user session, whenever other user's get their page refreshed, they will have the most updated data. If you want to have their page refreshed periodically, use a javascript timer.

Categories

Resources