net.tcp バインディングを介してクライアントから送信された実行時間の長いジョブを処理する自己ホスト型サービスがあります。ジョブが ( 内でTask
) 実行されている間、サービスは一方向のコールバックを介してクライアントにステータスの更新をプッシュします。これは正常に機能しますが、ジョブが完了したことをクライアントに通知するために別のコールバックを呼び出そうとすると (これも一方向)、クライアントでコールバックが受信/呼び出されることはありません。このプロセスで例外はありません。
私の Callback コントラクトは次のようになります。
public interface IWorkflowCallback
{
[OperationContract(IsOneWay = true)]
[ApplySharedTypeResolverAttribute]
void UpdateStatus(WorkflowJobStatusUpdate StatusUpdate);
[OperationContract(IsOneWay = true)]
[ApplySharedTypeResolverAttribute]
void NotifyJobCompleted(WorkflowJobCompletionNotice Notice);
}
コールバックを呼び出すサービスからのコード: (サービス実装自体ではなく、サービス実装から直接呼び出されます)
public WorkflowJobTicket AddToQueue(WorkflowJobRequest Request)
{
if (this.workflowEngine.WorkerPoolFull)
{
throw new QueueFullException();
}
var user = ServiceUserManager.CurrentUser;
var context = OperationContext.Current;
var workerId = this.workflowEngine.RunWorkflowJob(user, Request, new Object[]{new DialogServiceExtension(context)});
var workerjob = this.workflowEngine.FindJob(workerId);
var ticket = new WorkflowJobTicket()
{
JobRequestId = Request.JobRequestId,
JobTicketId = workerId
};
user.RegisterTicket<IWorkflowCallback>(ticket);
workerjob.WorkflowJobCompleted += this.NotifyJobComplete;
workerjob.Status.PropertyChanged += this.NotifyJobStatusUpdate;
this.notifyQueueChanged();
return ticket;
}
protected void NotifyJobStatusUpdate(object sender, PropertyChangedEventArgs e)
{
var user = ServiceUserManager.GetInstance().GetUserWithTicket((sender as WorkflowJobStatus).JobId);
Action<IWorkflowCallback> action = (callback) =>
{
ICommunicationObject communicationCallback = (ICommunicationObject)callback;
if (communicationCallback.State == CommunicationState.Opened)
{
try
{
var updates = (sender as WorkflowJobStatus).GetUpdates();
callback.UpdateStatus(updates);
}
catch (Exception)
{
communicationCallback.Abort();
}
}
};
user.Invoke<IWorkflowCallback>(action);
}
protected void NotifyJobComplete(WorkflowJob job, EventArgs e)
{
var user = ServiceUserManager.GetInstance().GetUserWithTicket(job.JobId);
Action<IWorkflowCallback> action = (callback) =>
{
ICommunicationObject communicationCallback = (ICommunicationObject)callback;
if (communicationCallback.State == CommunicationState.Opened)
{
try
{
var notice = new WorkflowJobCompletionNotice()
{
Ticket = user.GetTicket(job.JobId),
RuntimeOptions = job.RuntimeOptions
};
callback.NotifyJobCompleted(notice);
}
catch (Exception)
{
communicationCallback.Abort();
}
}
};
user.Invoke<IWorkflowCallback>(action);
}
このuser.Invoke<IWorkflowCallback>(action)
メソッドでは、Action
を介してコールバック チャネルのインスタンスが に渡されますOperationContext.GetCallbackChannel<IWorkflowCallback>()
。
ジョブ完了通知を呼び出すタスクがサービスによって実行されていることがわかりますが、クライアント エンドで呼び出しを受けません。さらに、完了通知が送信された後に更新コールバックを正常に呼び出すことができるため、チャネルに静かに障害が発生しているようには見えません。
ほぼ同じように実装されているこれら 2 つのコールバックのうち、1 つだけが機能するのはなぜですか?
洞察をお寄せいただきありがとうございます。