in src/Microsoft.ServiceFabric.Actors/Runtime/ActorManager.cs [167:265]
public async Task<T> DispatchToActorAsync<T>(
ActorId actorId,
ActorMethodContext actorMethodContext,
bool createIfRequired,
Func<ActorBase, CancellationToken, Task<T>> actorFunc,
string callContext,
bool timerCall,
CancellationToken cancellationToken)
{
this.ThrowIfClosed();
ExceptionDispatchInfo exceptionInfo = null;
Exception exception = null;
var retval = default(T);
// get activeActor from the activeActors table
using (var actorUseScope = this.GetActor(actorId, createIfRequired, timerCall))
{
var actor = actorUseScope.Actor;
// ***
// START: CRITICAL CODE
// ***
// Emit diagnostic info - before acquiring actor lock
var lockAcquireStartTime = this.DiagnosticsEventManager.AcquireActorLockStart(actor);
DateTime? lockAcquireFinishTime = null;
try
{
await
actor.ConcurrencyLock.Acquire(
callContext,
async innerActor => await this.HandleDirtyStateAsync(innerActor),
cancellationToken);
}
catch
{
// Emit diagnostic info - failed to acquire actor lock
this.DiagnosticsEventManager.AcquireActorLockFailed(actor);
throw;
}
// WARNING: DO NOT PUT ANY CODE BETWEEN CONCURRENCY LOCK ACQUIRE AND TRY
// THE LOCK NEEDS TO BE RELEASED IF THERE IS ANY EXCEPTION
try
{
// Emit diagnostic info - after acquiring actor lock
lockAcquireFinishTime = this.DiagnosticsEventManager.AcquireActorLockFinish(
actor,
lockAcquireStartTime);
retval =
await
this.DispatchToActorConcurrencyLockHeldAsync<T>(
actorId,
actorMethodContext,
actor,
actorFunc,
callContext,
cancellationToken);
}
catch (Exception e)
{
exception = e;
try
{
exceptionInfo = ExceptionDispatchInfo.Capture(e);
}
catch
{
// ignored
}
}
// WARNING: DO NOT PUT ANY CODE BELOW BEFORE THE LOCK IS RELEASED
// BECAUSE WE ARE NOT INSIDE A TRY-CATCH BLOCK
//
// signal that current execution is finished on this actor
// since there is no call pending or this was the first actor call in the callContext
await actor.ConcurrencyLock.ReleaseContext(callContext);
// Emit diagnostic info - after releasing actor lock
this.DiagnosticsEventManager.ReleaseActorLock(lockAcquireFinishTime);
// ***
// END: CRITICAL CODE
// ***
if (exceptionInfo != null)
{
exceptionInfo.Throw();
}
else if (exception != null)
{
throw exception;
}
return retval;
}
}