예제 #1
0
        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);
        }
예제 #2
0
        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);
        }