Azure Web角色中的后台线程

时间:2012-06-07 12:59:03

标签: c# multithreading azure azure-web-roles

可以通过WebRole.cs OnStart()方法运行一个线程,以便我们能够通过aspx页面访问它来执行后台工作吗? 我知道正确的方法是使用工作者角色,但我希望尽可能降低运营成本。

这个想法是创建一个总是在运行并等待作业的线程,例如,如果我想进行阻塞操作,如发送电子邮件,我将使用提供SendEmail方法的线程,是否可以做?如果是这样,你能否提供一些可以指出我正确方向的例子?

3 个答案:

答案 0 :(得分:10)

我想提出一个与Leon和David的解决方案不同的解决方案:

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

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

  • 您的网络应用程序:将消息发送到队列(例如“发送电子邮件至someone@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);
                }
            }
        }
    }
}

答案 1 :(得分:2)

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

答案 2 :(得分:1)

我在寻找“天蓝色计划任务”时发现了这一点:http://www.ronaldwidha.net/2011/02/23/cron-job-on-azure-using-scheduled-task-on-a-web-role-to-replace-azure-worker-role-for-background-job/

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