Reputation: 11
I have a design scenario that is giving me a few headaches and I'm wondering what solution is the best solution.
I have a dashboard-like application that polls information from a service that requires a java RMI connection to gather real time data. I'd like to implement that dashboard component in silverlight and provide the data using WCF.
I've designed a solution for this in the past with .net remoting and Windows forms. My previous design was a windows service, but I'm wondering if there is a way for me to host this service like application in IIS.
The service needs to: ->Open RMI connection (this i've done with ikvm) ->pull data at regular intervals ->Update clients new data has arrived (observer pattern)
Could I implement a singleton instance of my data collection class and register observers? Should i just host WCF in a windows service? Any other ideas?
Upvotes: 1
Views: 1065
Reputation: 8628
Full example of how to achieve this ...
using System
using Core.Services;
using System.Threading.Tasks;
using System.Web.Hosting;
public interface IISHostedProcessService : IRegisteredObject, IDisposable
{
Task Start();
}
public class CoreHostedProcess : IISHostedProcessService
{
protected bool running;
public CoreHostedProcess()
{
}
public virtual Task Start()
{
return Task.Run(() =>
{
running = true;
HostingEnvironment.RegisterObject(this);
});
}
public virtual void Stop(bool immediate)
{
running = false;
HostingEnvironment.UnregisterObject(this);
}
public virtual void Dispose()
{
}
}
Ok that's the core stuff defined, now we define a hosted process to do something useful like um, run tasks on a schedule ...
using log4net;
using System.Threading.Tasks;
using System.Timers;
using System;
using Core.Utilities.Objects.Entities;
using System.Linq;
using System.Net.Http;
using Core.Objects;
using Ninject;
public class TaskScheduler : CoreHostedProcess
{
static readonly ILog log = LogManager.GetLogger(typeof(TaskScheduler));
Timer timer = new Timer(60000);
IKernel kernel;
public TaskScheduler(IKernel kernel) : base()
{
this.kernel = kernel;
}
async void RunTasks(object sender, ElapsedEventArgs e)
{
//TODO: write code to fetch tasks and run them
}
public override async Task Start()
{
log.Info(" Initialising Task Scheduler.");
timer.Elapsed += RunTasks;
RunTasks(null, null);
timer.Start();
await base.Start();
}
public override void Stop(bool immediate)
{
log.Info(" Stopping Task Scheduler.");
timer.Stop();
base.Stop(immediate);
}
}
Ok now to use the hosted process ...
In IIS, within the applications advanced settings set "preload enabled" to true, to ensure the app remains loaded on the server after initial load.
When the app loads for example if using owin / in the old school global asax file you can add the following ...
public class Startup
{
static readonly ILog log = LogManager.GetLogger(typeof(Startup));
public static IKernel Kernel { get; private set; }
static List<IISHostedProcessService> hostedProcesses = new List<IISHostedProcessService>();
public void Configuration(IAppBuilder app)
{
hostedProcesses.Add(new TaskScheduler());
}
}
Now you should have everything you need to both define and initialize your TaskScheduler from within an IIS hosted C# application, I built an API for the management of the task data using OData that sits on top of my EF managed db so I could CRUD manage the set of tasks in the system.
After deploy I believe I have to hit the app at least once by simply making a request to it (any url), once loaded IIS will keep it running (thus keeping your Hosted Process running) until you stop the IIS application that hosts the process.
When the application is stopped the Stop method is called on your hosted processes that "un-registers the hosted process" and disposes of it on the server, thus tying in the hosted process to the IIS applications life cycle.
I figured it would be a bit too much to post the OData and EF code too. Hopefully this should do.
Upvotes: 0
Reputation: 25310
IIS is designed to handle HTTP connections and these are normally short lived. In order to do this kind of thing you have to make the client poll the server on a regular basis.
Upvotes: 0
Reputation: 46425
Web architecture essentially is only about responding to requests. You can simulate PUSH with repeated polling from the client, but if the client isn't actively seeking information, you can't push it on them.
Depending on what your client needs, it sounds like a webservice with a background cache and poll system to keep it updated would be best, as your client would always get the most up to date information straight away. The cache and update could be maintained by a number of different solutions, but your client would only see the standard webservice.
You could enhance it further by having a smaller interface as part of the webservice to allow the client to check if there is an update before downloading it is the size of the download offsets the roundtrip to check for the update.
Upvotes: 1