我正在 asp.net 完成一项作业,以特定间隔向用户发送通知电子邮件。
但问题是,由于服务器不是私有的,我无法在其上实现 Windows 服务。
有什么想法吗?
没有可靠的方法可以实现这一点。如果无法在主机上安装 Windows 服务,则可以编写一个端点(.aspx
或 .ashx
)来发送电子邮件,然后在其他站点上购买一项服务,该服务将通过发送 HTTP 请求定期 ping 此端点。显然,您应该将此端点配置为只能从您购买服务的提供商的 IP 地址访问,否则任何人都可以向端点发送 HTTP 请求并触发可能不希望的进程。
延伸阅读: The Dangers of Implementing Recurring Background Tasks In ASP.NET
.
有几种方法可以让代码在不需要 Windows 服务的时间间隔内执行。
一种选择是使用 Cache
类 - 使用采用CacheItemRemovedCallback
的Insert
重载之一 - 这将在删除缓存项时调用。你可以一次又一次地用这个回调重新添加缓存项......
不过,您需要做的第一件事是联系托管公司,看看他们是否已经为您提供了某种解决方案。
您可以在服务器上设置计划任务以调用具有所需操作的程序。
您始终可以使用System.Timer
并按特定时间间隔创建呼叫。您需要注意的是,这必须运行一次,例如在应用程序启动时,但是如果您有多个池,那么它可能会运行更多次,并且您还需要访问一些数据库来读取您的操作的数据。
using System.Timers;
var oTimer = new Timer();
oTimer.Interval = 30000; // 30 second
oTimer.Elapsed += new ElapsedEventHandler(MyThreadFun);
oTimer.Start();
private static void MyThreadFun(object sender, ElapsedEventArgs e)
{
// inside here you read your query from the database
// get the next email that must be send,
// you send them, and mark them as send, log the errors and done.
}
为什么我选择系统计时器:http://msdn.microsoft.com/en-us/magazine/cc164015.aspx
更多字数
我在更复杂的类中使用它,并且它的工作正常。我还提出了哪些观点。
- 发出应用程序停止的信号,以等待计时器结束。
- 使用互斥锁和数据库同步工作。
最简单的解决方案是利用 global.asax 应用程序事件
在应用程序启动事件上,将线程(或任务)创建到全局类中的静态单一实例变量中。
线程/任务/工作项将有一个无限循环,而(true){...} 包含您的"类似服务"的代码。
您还需要在循环中放置一个 Thread.Sleep(60000),这样它就不会占用不必要的 CPU 周期。
static void FakeService(object obj) {
while(true) {
try {
// - get a list of users to send emails to
// - check the current time and compare it to the interval to send a new email
// - send emails
// - update the last_email_sent time for the users
} catch (Exception ex) {
// - log any exceptions
// - choose to keep the loop (fake service) running or end it (return)
}
Thread.Sleep(60000); //run the code in this loop every ~60 seconds
}
}
编辑 由于您的任务或多或少是一个简单的计时器作业,因此应用程序池重置或其他错误中的任何 ACID 类型问题都不真正适用,因为它可以重新启动并随着任何数据损坏而继续行驶。但是,您也可以使用该线程来简单地执行对保存逻辑的 aspx 或 ashx 的请求。
new WebClient().DownloadString("http://localhost/EmailJob.aspx");