レオンとデビッドのソリューションとは異なるソリューションを提案します。
- David のソリューションは問題ありませんが、回復力がありません。タスクの処理中にインスタンス/プロセスがオフラインになるのは何ですか?
- レオンのソリューションは主にスケジュールされたジョブに適用されますが、電子メールの送信は常にスケジュールされているとは限りません (誰かがアプリに登録したときに電子メールを送信したい場合があります)。
このシナリオでは、Windows Azure ストレージ キュー (非常に安価) を使用することも検討する必要があります。
- Web アプリケーション: キューにメッセージを送信します (「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);
}
}
}
}
}