MSMQをお勧めします。:)なぜあなたがそれを使わないのか分かりませんが、あなたはあなたの質問でそれについて言及しました。これは、MSMQがアプリケーション間の耐久性のあるイベントのために設計されたものとほぼ同じです。これは主にpub/subメッセージモデルをサポートします...これは「理想的なソリューション」に基づいてまさに必要なものです。TCはパブリッシャーであり、TPはサブスクライバーです。TCはタスクを登録し、公開キューにメッセージをドロップします。TCがキューにメッセージを正常にドロップするために、TPタスクが稼働している必要はありませんが、TPタスクが実行されている場合、TPタスクは通知を受信し、キュー内のメッセージを優先順位に従って処理します。
MSMQがオプションでない場合は、WCFを使用することもできます。pub / subではなく、WCFを使用すると、FAF(ファイアアンドフォーゲット)メッセージモデルを選択できます。TPは、TCが消費するサービスを公開します。TCは、TPに新しいタスクを通知するために、TPのサービスにメッセージを送信するだけで済みます。このモデルの欠点は、TCがTPに依存していることです。これは、アイデアよりも少ない可能性があります。TPは、TPのサービスに依存しているため、TCが正常に機能するにはTPも実行されている必要があります。MSMQアプローチでは、TPもTCも相互に依存せず、MSMQにのみ依存します(低結合アプローチ)。
編集:
MSMQを使用してTCからイベントを発生させ、TPのイベントに応答する方法の例。
// TC message queue manager, sends messages
public class TaskMessageQueueManager
{
public void NotifySubscribersOfNewTasks()
{
var queue = getQueue(".\private$\TaskNotifications");
queue.Send("Tasks waiting.");
}
private MessageQueue getQueue(string name)
{
MessageQueue queue = null;
try
{
if (!MessageQueue.Exists(name))
{
queue = MessageQueue.Create(name);
}
else
{
queue = new MessageQueue(name);
}
}
catch (Exception ex)
{
throw new InvalidOperationException("An error occurred while retrieving the message queue '" + name + "'.", ex);
}
return queue;
}
}
// TP message queue handler, receives messages
public class TaskMessageQueueHandler
{
private Thread m_thread;
private ManualResetEvent m_signal;
public void Start()
{
m_signal = new ManualResetEvent(false);
m_thread = new Thread(MSMQReceiveLoop);
m_thread.Start();
}
public void Stop()
{
m_signal.Set();
}
private void MSMQReceiveLoop()
{
bool running = true;
MessageQueue queue = getQueue(".\private$\TaskNotifications");
while (running)
{
try
{
var message = queue.Receive(); // Blocks here until a message is received by MSMQ
if (message.Body.ToString() == "Tasks waiting.")
{
// TODO: Fire off process, perhaps another thread, to handle waiting tasks
}
if (m_signal.WaitOne(10)) // Non-blocking check for exit signal
{
running = false; // If Stop method has been called, the signal will be set and we can end loop
}
}
catch
{
// handle error
running = false;
}
}
}
}
メッセージは単純なテキストである必要はありません。オブジェクトまたはオブジェクトグラフを送信できます。デフォルトでは、自動的にシリアル化され、XMLとしてフォーマットされます。必要に応じて、データをバイナリ形式でシリアル化することもできると思います。いずれにせよ、Thread.Sleep呼び出しやポーリングがどこにも存在しないことに気付くでしょう。ループはManualResetEventに基づいて終了し、ハードアボートなしでスレッドをクリーンに終了できます。