public async Task InvokeRemotely( Expression <Action <CancellationToken> > invocation, CancellationToken ct, TimeSpan cancellationTimeout, ForcedCancellationMode forcedCancellationMode, SecurityZone securityZone, WorkerProcessRef workerProcessRef ) { var request = InvocationRequest.FromExpression(invocation); await this.InvokeRemotely( request, ct, cancellationTimeout, forcedCancellationMode, securityZone, workerProcessRef) .ConfigureAwait(false); }
private Task <object> InvokeRemotely( InvocationRequest request, CancellationToken ct, TimeSpan cancellationTimeout, ForcedCancellationMode forcedCancellationMode, SecurityZone securityZone, WorkerProcessRef workerProcessRef ) { const State nextState = State.Busy; lock (this.stateLock) { if (this.CurrentState != State.Idle) { throw new InvalidOperationException( "Worker process is not ready. Current state is: " + this.CurrentState); } if (!this.process.IsAlive) { this.OnProcessDead(this, EventArgs.Empty); throw new InvalidOperationException("Worker process not alive / crashed."); } this.state = nextState; this.activeTcs = new TaskCompletionSource <object>(); if (workerProcessRef != null) { workerProcessRef.WorkerProcess = this.process.Process; } // this is the latest time to check whether the task has already been cancelled, before actually // starting the task! if (ct.IsCancellationRequested) { this.activeTcs.TrySetCanceled(); this.activeTcs = null; return(this.activeTcs.Task); } } // outside lock! this.OnCurrentStateChanged(nextState); ct.Register(() => { try { this.serverProxy.Cancel(cancellationTimeout, forcedCancellationMode); } catch (RemotingException) { if (!this.process.IsAlive) { // worker killed itself or crashed: ignore! return; } throw; } }); this.serverProxy.InvokeAsync(request.ToPortableInvocationRequest(), securityZone); // Calling Cancel(..) on the server is only handled if there's a invocation request being handled! // there's the chance that task was canceled before it was actually started. It might have happened // before registering the cancel callback, as well. // At this point we now for sure, that the task has been started! if (ct.IsCancellationRequested) { this.serverProxy.Cancel(cancellationTimeout, forcedCancellationMode); } return(this.activeTcs.Task); }