- ジョブ マネージャーが新しいメッセージを受け取り、ジョブを起動します。
- ジョブが開始され、メッセージが処理され、応答メッセージが送信されます。
- この時点で、ジョブは応答に対する応答を待ちます。
まず、Async CTP は非同期操作を非常にうまく処理しますが、非同期イベントはあまり処理しないことに注意してください。Rx ベースのアプローチを検討することをお勧めします。しかし、ここでは Async CTP について説明しましょう。
タスクを作成するには、次の 2 つの基本的なオプションがあります。
- デリゲート付き。たとえば、
Task.Factory.StartNew
スレッド プールでデリゲートを実行します。カスタム タスク ファクトリとスケジューラを使用すると、タスク デリゲートのオプションが増えます (たとえば、デリゲートを STA スレッドで実行するように指定するなど)。
- デリゲートなし。たとえば、
TaskFactory.FromAsync
既存のBegin
/End
メソッドのペアをラップしTaskEx.FromResult
、「将来の定数」を返し、明示的TaskCompletionSource
に制御するために使用できます(両方とも内部的に使用します)。Task
FromAsync
FromResult
TCS
ジョブ処理が CPU バウンドの場合は、それを に渡すのが理にかなっていTask.Factory.StartNew
ます。ジョブ処理は CPU バウンドであると仮定します。
ジョブ マネージャーの擬似コード:
// Responds to a new message by starting a new job on the thread pool.
private void RespondToNewMessage(IPacketMsg message)
{
IJob job = ..;
Task.Factory.StartNew(job.RunJob(message));
}
// Holds tasks waiting for a response.
private ConcurrentDictionary<int, TaskCompletionSource<IResponse>> responseTasks = ..;
// Asynchronously gets a response for the specified reply.
public Task<IResponse> GetResponseForReplyAsync(int replyId)
{
var tcs = new TaskCompletionSource<IResponse>();
responseTasks.Add(replyId, tcs);
return tcs.Task;
}
// Responds to a new response by completing and removing its task.
private void RespondToResponse(IResponse response)
{
var tcs = responseTasks[response.ReplyId];
responseTasks.Remove(response.ReplyId);
tcs.TrySetComplete(response);
}
アイデアは、ジョブ マネージャーが未解決の応答のリストも管理するというものです。これを実現するためにint
、ジョブ マネージャーがどの応答とどの応答が一致するかを判断するために使用できる単純な応答識別子を導入しました。
ジョブは次のように機能するようになりました。
public override void RunJob(IPacketMsg packet)
{
// handle packet
var myReply = new Packet();
var response = jobManager.GetResponseForReplyAsync(myReply.ReplyId);
SendReply(myReply);
await response;
}
ジョブをスレッド プール スレッドに配置しているため、いくつか注意が必要な点があります。
GetResponseForReplyAsync
応答が送信される前に呼び出され(タスクを登録する)必要があり、await
後で編集されます。これは、返信が送信され、登録する前に応答が受信されるという状況を回避するためです。
RespondToResponse
タスクを完了すると同じ ID で別の返信が送信される場合に備えて、完了する前にタスク登録を削除します。
ジョブがスレッド プール スレッドに配置する必要がないほど短い場合は、ソリューションを単純化できます。