コード例 #1
0
        public override async Task <IDicomClientState> GetNextStateAsync(DicomClientCancellation cancellation)
        {
            if (cancellation.Token.IsCancellationRequested)
            {
                switch (cancellation.Mode)
                {
                case DicomClientCancellationMode.ImmediatelyReleaseAssociation:
                    _dicomClient.Logger.Warn($"[{this}] Cancellation is requested before requests could be sent, releasing association ...");
                    return(await _dicomClient.TransitionToReleaseAssociationState(_initialisationParameters, cancellation).ConfigureAwait(false));

                case DicomClientCancellationMode.ImmediatelyAbortAssociation:
                    _dicomClient.Logger.Warn($"[{this}] Cancellation is requested before requests could be sent, aborting association ...");
                    return(await _dicomClient.TransitionToAbortState(_initialisationParameters, cancellation).ConfigureAwait(false));

                default:
                    throw new ArgumentOutOfRangeException(nameof(cancellation.Mode), cancellation.Mode, "Unknown cancellation mode");
                }
            }

            _disposables.Add(cancellation.Token.Register(() => _sendRequestsCancellationTokenSource.Cancel()));
            _disposables.Add(cancellation.Token.Register(() => _onCancellationTaskCompletionSource.TrySetResultAsynchronously(true)));

            _dicomClient.Logger.Debug($"[{this}] Sending DICOM requests");

            await SendInitialRequests().ConfigureAwait(false);

            var allRequestsHaveCompleted = KeepSendingUntilAllRequestsHaveCompletedAsync();
            var onReceiveAbort           = _onAbortReceivedTaskCompletionSource.Task;
            var onDisconnect             = _onConnectionClosedTaskCompletionSource.Task;
            var onCancellation           = _onCancellationTaskCompletionSource.Task;

            var winner = await Task.WhenAny(
                allRequestsHaveCompleted,
                onReceiveAbort,
                onDisconnect,
                onCancellation
                )
                         .ConfigureAwait(false);

            if (winner == allRequestsHaveCompleted)
            {
                if (_numberOfSentRequests < _maximumNumberOfRequestsPerAssociation)
                {
                    _dicomClient.Logger.Debug($"[{this}] All requests are done, going to linger association now...");
                    return(await _dicomClient.TransitionToLingerState(_initialisationParameters, cancellation).ConfigureAwait(false));
                }

                _dicomClient.Logger.Debug($"[{this}] The maximum number of requests per association ({_maximumNumberOfRequestsPerAssociation}) have been sent, immediately releasing association now...");
                return(await _dicomClient.TransitionToReleaseAssociationState(_initialisationParameters, cancellation).ConfigureAwait(false));
            }

            if (winner == onCancellation)
            {
                switch (cancellation.Mode)
                {
                case DicomClientCancellationMode.ImmediatelyReleaseAssociation:
                    _dicomClient.Logger.Warn($"[{this}] Cancellation requested, releasing association...");
                    return(await _dicomClient.TransitionToReleaseAssociationState(_initialisationParameters, cancellation).ConfigureAwait(false));

                case DicomClientCancellationMode.ImmediatelyAbortAssociation:
                    _dicomClient.Logger.Warn($"[{this}] Cancellation requested, aborting association...");
                    return(await _dicomClient.TransitionToAbortState(_initialisationParameters, cancellation).ConfigureAwait(false));

                default:
                    throw new ArgumentOutOfRangeException(nameof(cancellation.Mode), cancellation.Mode, "Unknown cancellation mode");
                }
            }

            if (winner == onReceiveAbort)
            {
                _dicomClient.Logger.Warn($"[{this}] Association is aborted while sending requests, cleaning up...");
                var abortReceivedResult = onReceiveAbort.Result;
                var exception           = new DicomAssociationAbortedException(abortReceivedResult.Source, abortReceivedResult.Reason);
                return(await _dicomClient.TransitionToCompletedWithErrorState(_initialisationParameters, exception, cancellation).ConfigureAwait(false));
            }

            if (winner == onDisconnect)
            {
                _dicomClient.Logger.Debug($"[{this}] Disconnected while sending requests, cleaning up...");
                var connectionClosedEvent = await onDisconnect.ConfigureAwait(false);

                if (connectionClosedEvent.Exception == null)
                {
                    return(await _dicomClient.TransitionToCompletedState(_initialisationParameters, cancellation).ConfigureAwait(false));
                }
                else
                {
                    return(await _dicomClient.TransitionToCompletedWithErrorState(_initialisationParameters, connectionClosedEvent.Exception, cancellation).ConfigureAwait(false));
                }
            }

            throw new DicomNetworkException("Unknown winner of Task.WhenAny in DICOM client, this is likely a bug: " + winner);
        }
コード例 #2
0
        public override async Task <IDicomClientState> GetNextStateAsync(DicomClientCancellation cancellation)
        {
            if (cancellation.Token.IsCancellationRequested)
            {
                return(await OnCancel(cancellation).ConfigureAwait(false));
            }

            if (_dicomClient.QueuedRequests.Any())
            {
                _dicomClient.Logger.Debug($"[{this}] DICOM client already has requests again, immediately moving back to sending requests");
                return(await _dicomClient.TransitionToSendingRequestsState(_initialisationParameters, cancellation).ConfigureAwait(false));
            }

            _disposables.Add(cancellation.Token.Register(() => _onCancellationRequestedTaskCompletionSource.TrySetResultAsynchronously(true)));

            var onRequestIsAdded = _onRequestAddedTaskCompletionSource.Task;
            var onReceiveAbort   = _onAbortReceivedTaskCompletionSource.Task;
            var onDisconnect     = _onConnectionClosedTaskCompletionSource.Task;
            var onLingerTimeout  = Task.Delay(_dicomClient.AssociationLingerTimeoutInMs, _lingerTimeoutCancellationTokenSource.Token);
            var onCancel         = _onCancellationRequestedTaskCompletionSource.Task;

            var winner = await Task.WhenAny(onRequestIsAdded, onReceiveAbort, onDisconnect, onLingerTimeout, onCancel)
                         .ConfigureAwait(false);

            if (winner == onRequestIsAdded)
            {
                _dicomClient.Logger.Debug($"[{this}] A new request was added before linger timeout of {_dicomClient.AssociationLingerTimeoutInMs}ms, reusing association");
                return(await _dicomClient.TransitionToSendingRequestsState(_initialisationParameters, cancellation).ConfigureAwait(false));
            }

            if (winner == onLingerTimeout)
            {
                _dicomClient.Logger.Debug($"[{this}] Linger timed out after {_dicomClient.AssociationLingerTimeoutInMs}ms, releasing association");
                return(await _dicomClient.TransitionToReleaseAssociationState(_initialisationParameters, cancellation).ConfigureAwait(false));
            }

            if (winner == onReceiveAbort)
            {
                _dicomClient.Logger.Warn($"[{this}] Association was aborted while lingering the association");
                var abortReceivedResult = onReceiveAbort.Result;
                var exception           = new DicomAssociationAbortedException(abortReceivedResult.Source, abortReceivedResult.Reason);
                return(await _dicomClient.TransitionToCompletedWithErrorState(_initialisationParameters, exception, cancellation).ConfigureAwait(false));
            }

            if (winner == onDisconnect)
            {
                _dicomClient.Logger.Warn($"[{this}] Disconnected while lingering the association");
                var connectionClosedEvent = await onDisconnect.ConfigureAwait(false);

                if (connectionClosedEvent.Exception == null)
                {
                    return(await _dicomClient.TransitionToCompletedState(_initialisationParameters, cancellation).ConfigureAwait(false));
                }

                return(await _dicomClient.TransitionToCompletedWithErrorState(_initialisationParameters, connectionClosedEvent.Exception, cancellation).ConfigureAwait(false));
            }

            if (winner == onCancel)
            {
                return(await OnCancel(cancellation).ConfigureAwait(false));
            }

            throw new DicomNetworkException("Unknown winner of Task.WhenAny in DICOM client, this is likely a bug: " + winner);
        }
コード例 #3
0
        public override async Task <IDicomClientState> GetNextStateAsync(DicomClientCancellation cancellation)
        {
            if (cancellation.Token.IsCancellationRequested)
            {
                _dicomClient.Logger.Warn($"[{this}] Cancellation requested before association request was made, going to disconnect now");
                return(await _dicomClient.TransitionToCompletedState(_initialisationParameters, cancellation).ConfigureAwait(false));
            }

            await SendAssociationRequest().ConfigureAwait(false);

            _disposables.Add(cancellation.Token.Register(() => _onCancellationRequestedTaskCompletionSource.TrySetResultAsynchronously(true)));

            var associationIsAccepted      = _onAssociationAcceptedTaskCompletionSource.Task;
            var associationIsRejected      = _onAssociationRejectedTaskCompletionSource.Task;
            var abortReceived              = _onAbortReceivedTaskCompletionSource.Task;
            var onDisconnect               = _onConnectionClosedTaskCompletionSource.Task;
            var associationRequestTimesOut = Task.Delay(_dicomClient.AssociationRequestTimeoutInMs, _associationRequestTimeoutCancellationTokenSource.Token);
            var onCancellationRequested    = _onCancellationRequestedTaskCompletionSource.Task;

            var winner = await Task.WhenAny(
                associationIsAccepted,
                associationIsRejected,
                abortReceived,
                onDisconnect,
                associationRequestTimesOut,
                onCancellationRequested
                ).ConfigureAwait(false);

            if (winner == associationIsAccepted)
            {
                _dicomClient.Logger.Debug($"[{this}] Association is accepted");
                var association = associationIsAccepted.Result.Association;
                _dicomClient.NotifyAssociationAccepted(new EventArguments.AssociationAcceptedEventArgs(association));
                return(await _dicomClient.TransitionToSendingRequestsState(_initialisationParameters, association, cancellation).ConfigureAwait(false));
            }

            if (winner == associationIsRejected)
            {
                var associationRejectedResult = associationIsRejected.Result;

                _dicomClient.Logger.Warn($"[{this}] Association is rejected");
                var result = associationRejectedResult.Result;
                var source = associationRejectedResult.Source;
                var reason = associationRejectedResult.Reason;
                _dicomClient.NotifyAssociationRejected(new EventArguments.AssociationRejectedEventArgs(result, source, reason));
                var exception = new DicomAssociationRejectedException(result, source, reason);
                return(await _dicomClient.TransitionToCompletedWithErrorState(_initialisationParameters, exception, cancellation).ConfigureAwait(false));
            }

            if (winner == abortReceived)
            {
                _dicomClient.Logger.Warn($"[{this}] Association is aborted");
                var abortReceivedResult = abortReceived.Result;
                var exception           = new DicomAssociationAbortedException(abortReceivedResult.Source, abortReceivedResult.Reason);
                return(await _dicomClient.TransitionToCompletedWithErrorState(_initialisationParameters, exception, cancellation).ConfigureAwait(false));
            }

            if (winner == onDisconnect)
            {
                _dicomClient.Logger.Warn($"[{this}] Disconnected");
                var connectionClosedEvent = await onDisconnect.ConfigureAwait(false);

                if (connectionClosedEvent.Exception == null)
                {
                    return(await _dicomClient.TransitionToCompletedState(_initialisationParameters, cancellation).ConfigureAwait(false));
                }
                else
                {
                    return(await _dicomClient.TransitionToCompletedWithErrorState(_initialisationParameters, connectionClosedEvent.Exception, cancellation));
                }
            }

            if (winner == associationRequestTimesOut)
            {
                _dicomClient.Logger.Warn($"[{this}] Association request timeout");
                return(await _dicomClient.TransitionToCompletedState(_initialisationParameters, cancellation).ConfigureAwait(false));
            }

            if (winner == onCancellationRequested)
            {
                _dicomClient.Logger.Warn($"[{this}] Cancellation requested while requesting association, aborting now...");
                return(await _dicomClient.TransitionToAbortState(_initialisationParameters, cancellation).ConfigureAwait(false));
            }

            throw new DicomNetworkException("Unknown winner of Task.WhenAny in DICOM client, this is likely a bug: " + winner);
        }
コード例 #4
0
        public override async Task <IDicomClientState> GetNextStateAsync(DicomClientCancellation cancellation)
        {
            // We can mostly ignore the cancellation token in this state, unless the cancellation mode is set to "Immediately abort"
            if (cancellation.Token.IsCancellationRequested && cancellation.Mode == DicomClientCancellationMode.ImmediatelyAbortAssociation)
            {
                return(await _dicomClient.TransitionToAbortState(_initialisationParameters, cancellation).ConfigureAwait(false));
            }

            await _initialisationParameters.Connection.SendAssociationReleaseRequestAsync().ConfigureAwait(false);

            if (cancellation.Mode == DicomClientCancellationMode.ImmediatelyAbortAssociation)
            {
                _disposables.Add(cancellation.Token.Register(() => _onAbortRequestedTaskCompletionSource.TrySetResult(true)));
            }

            var onAssociationRelease        = _onAssociationReleasedTaskCompletionSource.Task;
            var onAssociationReleaseTimeout = Task.Delay(_dicomClient.ClientOptions.AssociationReleaseTimeoutInMs, _associationReleaseTimeoutCancellationTokenSource.Token);
            var onReceiveAbort = _onAbortReceivedTaskCompletionSource.Task;
            var onDisconnect   = _onConnectionClosedTaskCompletionSource.Task;
            var onAbort        = _onAbortRequestedTaskCompletionSource.Task;

            var winner = await Task.WhenAny(
                onAssociationRelease,
                onAssociationReleaseTimeout,
                onReceiveAbort,
                onDisconnect,
                onAbort)
                         .ConfigureAwait(false);

            if (winner == onAssociationRelease)
            {
                _dicomClient.NotifyAssociationReleased();

                _dicomClient.Logger.Debug($"[{this}] Association release response received, disconnecting...");
                return(await _dicomClient.TransitionToCompletedState(_initialisationParameters, cancellation).ConfigureAwait(false));
            }

            if (winner == onAssociationReleaseTimeout)
            {
                _dicomClient.Logger.Debug($"[{this}] Association release timed out, aborting...");
                return(await _dicomClient.TransitionToAbortState(_initialisationParameters, cancellation).ConfigureAwait(false));
            }

            if (winner == onReceiveAbort)
            {
                _dicomClient.Logger.Debug($"[{this}] Association aborted, disconnecting...");
                var abortReceivedResult = onReceiveAbort.Result;
                var exception           = new DicomAssociationAbortedException(abortReceivedResult.Source, abortReceivedResult.Reason);
                return(await _dicomClient.TransitionToCompletedWithErrorState(_initialisationParameters, exception, cancellation).ConfigureAwait(false));
            }

            if (winner == onDisconnect)
            {
                _dicomClient.Logger.Debug($"[{this}] Disconnected during association release, cleaning up...");

                /*
                 * Sometimes, the server is very swift at closing the connection, before we get a chance to process the Association Release response
                 */
                _dicomClient.NotifyAssociationReleased();

                var connectionClosedEvent = await onDisconnect.ConfigureAwait(false);

                if (connectionClosedEvent.Exception == null)
                {
                    return(await _dicomClient.TransitionToCompletedState(_initialisationParameters, cancellation).ConfigureAwait(false));
                }
                else
                {
                    return(await _dicomClient.TransitionToCompletedWithErrorState(_initialisationParameters, connectionClosedEvent.Exception, cancellation).ConfigureAwait(false));
                }
            }

            if (winner == onAbort)
            {
                _dicomClient.Logger.Warn($"[{this}] Cancellation requested during association release, immediately aborting association");
                return(await _dicomClient.TransitionToAbortState(_initialisationParameters, cancellation).ConfigureAwait(false));
            }

            throw new DicomNetworkException("Unknown winner of Task.WhenAny in DICOM client, this is likely a bug: " + winner);
        }