5

我在共享环境中的 GoDaddy 上运行了一个 ASP .NET 网站。该应用程序是一种基于订阅的服务,具有向用户定期计费的选项。

每小时,我们都需要与我们的支付处理器同步用户数据,以更新已升级或取消帐户的用户。支付处理器没有调用 URL 或以其他方式通知我们更改的机制。

问题:我们需要创建一个后台线程,以预定义的时间间隔运行一些代码。有一些关于 .NET 中后台任务的好文章,但我敢肯定,可能有更简单的方法来解决这个问题。也许是一个可以调用函数的应用程序范围的计时器等。

限制:共享环境不允许windows服务、外部应用程序、完全信任等。

由于这是一个生产应用程序,我想使用最安全的方法,而不是使用 IIS。

4

3 回答 3

6

我有一个类似的问题,我正在开发一个 ASP 概念证明并使用一个后台线程来执行可能需要几个小时的任务。问题是,ASP.Net 可以随时回收 AppDomain(杀死我的后台线程)。

为了防止这种情况,您可以将您的后台线程注册到 ASP.Net,以便它会通知您的线程关闭。为此,请实现以下接口:

public interface IRegisteredObject
{
    void Stop(bool immediate);
}

并使用以下静态方法将您的对象注册到 ASP:

HostingEnvironment.RegisterObject(this);

当 ASP.NET 拆除 AppDomain 时,它将首先尝试对所有已注册的对象调用 Stop 方法。在大多数情况下,它会调用此方法两次,一次将立即设置为 false。这让你的代码有一点时间来完成它正在做的事情。ASP.NET 为 IRegisteredObject 的所有实例提供总共 30 秒的时间来完成它们的工作,而不是每个实例的 30 秒。在该时间跨度之后,如果还有任何已注册的对象,它将再次调用它们,并将立即设置为 true。

通过阻止 Stop 方法返回(通过在工作人员忙碌时锁定字段),我们阻止 ASP 关闭 AppDomain 直到我们的工作完成。

public void Stop(bool immediate)
{
    lock (_lock)
    {
        _shuttingDown = true;
    }
    HostingEnvironment.UnregisterObject(this); 
}

public void DoWork(Action work)
{
    lock (_lock)
    {
        if (_shuttingDown)
        {
            return;
        }
        work();
    }
}

使用任务而不是操作来从取消选项中受益。对于您的特定情况,您可以启动一个执行此类任务的计时器。

PS。这是一个 hack,ASP 并不意味着运行后台任务,所以尽可能使用 Windows 服务或 WCF 服务!我使用它是因为它简化了开发、维护和安装。

有关更多信息,请参阅我的来源:http ://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx

于 2013-06-13T12:52:31.467 回答
3

为 2018 年更新 - Hangfire NuGet 包非常适合这个

于 2018-05-29T13:01:25.007 回答
0

由于没有答案,我想我会发布我的解决方案以防它帮助其他人。

无论如何都不是理想的方法,但对于那些可能从中受益的人,我在另一个 Linux 托管帐户上创建了一个 cron 作业,我们必须调用所需的 ASP .NET url。管理恐怖,但完成了工作。

于 2012-01-11T06:06:18.993 回答