public async Task <IAsyncQuickInfoSession> TriggerQuickInfoAsync(
            ITextView textView,
            ITrackingPoint triggerPoint,
            QuickInfoSessionOptions options,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // Caret element requires UI thread.
            await this.joinableTaskContext.Factory.SwitchToMainThreadAsync();

            // We switched threads and there is some latency, so ensure that we're still not canceled.
            cancellationToken.ThrowIfCancellationRequested();

            // Dismiss any currently open session.
            var currentSession = this.GetSession(textView);

            if (currentSession != null)
            {
                await currentSession.DismissAsync();
            }

            // Get the trigger point from the caret if none is provided.
            triggerPoint = triggerPoint ?? textView.TextSnapshot.CreateTrackingPoint(
                textView.Caret.Position.BufferPosition,
                PointTrackingMode.Negative);

            var newSession = new AsyncQuickInfoSession(
                this.OrderedSourceProviders,
                this.guardedOperations,
                this.joinableTaskContext,
                this.toolTipService,
                textView,
                triggerPoint,
                options,
                null);

            // StartAsync() is responsible for dispatching a StateChange
            // event if canceled so no need to clean these up on cancellation.
            newSession.StateChanged += this.OnStateChanged;
            textView.Properties.AddProperty(typeof(AsyncQuickInfoSession), newSession);

            try
            {
                await newSession.StartAsync(cancellationToken);
            }
            catch (OperationCanceledException) when(!cancellationToken.IsCancellationRequested)
            {
                // Don't throw OperationCanceledException unless the caller canceled us.
                // This can happen if computation was canceled by a quick info source
                // dismissing the session during computation, which we want to consider
                // more of a 'N/A' than an error.
                return(null);
            }

            return(newSession);
        }