在IIS中托管一个长时间运行的进程

时间:2009-10-19 15:49:24

标签: .net wcf silverlight iis

我有一个设计方案让我有些头疼,我想知道什么解决方案是最好的解决方案。

我有一个类似仪表板的应用程序,可以轮询来自需要Java RMI连接的服务的信息来收集实时数据。我想在Silverlight中实现该仪表板组件并使用WCF提供数据。

我在过去使用.net远程处理和Windows窗体设计了一个解决方案。我以前的设计是一个Windows服务,但我想知道是否有办法让我像IIS中的应用程序一样托管这项服务。

该服务需要: - >打开RMI连接(这是我用ikvm完成的) - >定期提取数据 - >更新客户端新数据已到达(观察者模式)

我可以实现数据集合类的单例实例并注册观察者吗?我应该只在Windows服务中托管WCF吗?还有其他想法吗?

3 个答案:

答案 0 :(得分:1)

Web架构本质上只是响应请求。您可以通过客户端的重复轮询来模拟PUSH,但如果客户端没有主动搜索信息,则无法将其推送到它们上面。

根据您的客户需求,它听起来像一个带有后台缓存和民意调查系统的网络服务,以保持更新是最好的,因为您的客户将始终获得最新的信息。缓存和更新可以由许多不同的解决方案维护,但您的客户端只能看到标准的Web服务。

您可以通过将较小的界面作为Web服务的一部分来进一步增强它,以允许客户端在下载之前检查是否有更新,下载的大小会抵消轮次以检查更新。

答案 1 :(得分:0)

IIS旨在处理HTTP连接,这些通常是短暂的。为了做这种事情,你必须让客户定期轮询服务器。

答案 2 :(得分:0)

如何实现这一目标的完整示例...

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()
    {

    }
}

好的,这是定义的核心内容,现在我们定义一个托管流程来执行像um这样有用的事情,按计划运行任务......

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

现在好了,使用托管进程......

在IIS中,在应用程序高级设置中设置"预加载"为true,以确保在初始加载后应用程序仍然在服务器上加载。

当应用程序加载时,例如,如果在旧学校的全局asax文件中使用owin /,则可以添加以下内容...

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());
    }
}

现在你应该拥有从IIS托管的C#应用​​程序中定义和初始化TaskScheduler所需的一切,我使用位于我的EF托管数据库之上的OData构建了一个用于管理任务数据的API,所以我可以CRUD管理系统中的任务集。

部署后我相信我必须通过简单地向它发出请求(任何网址)至少一次点击应用程序,一旦加载IIS将使其保持运行(从而保持托管进程运行),直到您停止IIS应用程序为止主持这个过程。

当应用程序停止时,将在托管进程上调用Stop方法,以取消注册托管进程&#34;并在服务器上处理它,从而将托管进程绑定到IIS应用程序生命周期。

我认为发布OData和EF代码也有点太多了。 希望这应该做到。