6

是否可以从 WebRole.cs OnStart() 方法运行线程,以便我们能够通过 aspx 页面访问它以执行后台工作?我知道正确的做法是使用 Worker Role,但我希望将运行成本保持在尽可能低的水平。

这个想法是创建一个始终运行并等待作业的线程,例如,如果我想做一个阻塞操作,比如发送电子邮件,我会使用提供 SendEmail 方法的线程,有可能吗?如果是这样,您能否提供一些可以为我指明正确方向的示例?

4

3 回答 3

10

我会建议一个不同于 Leon 和 David 的解决方案的解决方案:

  • 大卫的解决方案还可以,但没有弹性。处理任务时实例/进程离线是什么?
  • Leon 的解决方案主要适用于预定的工作,但发送电子邮件并不总是预定的(也许您想在有人在您的应用程序中注册时发送电子邮件)。

您应该考虑的另一个选项是在这种情况下使用 Windows Azure 存储队列(它们非常便宜):

  • 您的 Web 应用程序:向队列发送消息(例如“向某人@someone.com 发送电子邮件”)
  • WebRole.cs:在启动实例时产生一个新线程并让它监听来自该队列的消息。每当消息到达时,对其进行处理。如果成功,则从队列中删除消息。

这种解决方案有很多优点。WebRole.cs 在与您的 Web 应用程序不同的进程中运行,因此对请求线程没有影响。除此之外,如果由于某种原因发送邮件失败,邮件将留在队列中,并在下一次处理。这将确保您在应用程序或进程崩溃时不会丢失任何要执行的任务。

这是一个帮助您入门的示例。请注意,如果您希望此代码可用于生产(重试策略、异常处理、退避轮询……),则需要改进此代码:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Diagnostics;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
using System.Threading.Tasks;

namespace MvcWebRole1
{
    public class WebRole : RoleEntryPoint
    {
        public override bool OnStart()
        {
            Task.Factory.StartNew(InitializeQueueListener);
            return base.OnStart();
        }

        private void InitializeQueueListener()
        {
            Microsoft.WindowsAzure.CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
            {
                configSetter(Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.GetConfigurationSettingValue(configName));
            });


            var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
            var queueStorage = storageAccount.CreateCloudQueueClient();
            var queue = queueStorage.GetQueueReference("myqueue");
            queue.CreateIfNotExist();

            while (true)
            {
                CloudQueueMessage msg = queue.GetMessage();
                if (msg != null)
                {
                    // DO SOMETHING HERE
                    queue.DeleteMessage(msg);
                }
                else
                {
                    System.Threading.Thread.Sleep(1000);
                }
            }
        }
    }
}
于 2012-06-07T13:32:11.673 回答
2

绝对可以创建一个线程(或许多线程)。Web 角色基本上是 Windows 2008 Server。您不需要单独的 Worker 角色来设置后台任务。当然,您可以拥有一个单独的工作者角色,这将允许您独立于您的 Web 角色实例来扩展这些实例。这是您需要平衡性能/扩展与成本的地方。

于 2012-06-07T13:11:54.803 回答
1

我在寻找“天蓝色计划任务”时发现了这一点:http ://www.ronaldwidha.net/2011/02/23/cron-job-on-azure-using-scheduled-task-on-a-web-角色替换天蓝色工人角色换后台作业/

看起来正是您正在寻找的东西。

于 2012-06-07T13:10:44.990 回答