public async Task <CompletionReason> ServeConnection(TaskCompletionSource <TimeSpan?> timeoutCompletionSource = null, CancellationToken cancellationToken = default(CancellationToken))
            {
                timeoutCompletionSource = timeoutCompletionSource ?? new TaskCompletionSource <TimeSpan?>();
                try
                {
                    BuildRequest request;
                    try
                    {
                        Log("Begin reading request.");
                        request = await _clientConnection.ReadBuildRequest(cancellationToken).ConfigureAwait(false);

                        Log("End reading request.");
                    }
                    catch (Exception e)
                    {
                        LogException(e, "Error reading build request.");
                        return(CompletionReason.CompilationNotStarted);
                    }

                    CheckForNewKeepAlive(request, timeoutCompletionSource);

                    // Kick off both the compilation and a task to monitor the pipe for closing.
                    var buildCts        = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                    var compilationTask = ServeBuildRequest(request, buildCts.Token);
                    var monitorTask     = _clientConnection.CreateMonitorDisconnectTask(buildCts.Token);
                    await Task.WhenAny(compilationTask, monitorTask).ConfigureAwait(false);

                    // Do an 'await' on the completed task, preference being compilation, to force
                    // any exceptions to be realized in this method for logging.
                    CompletionReason reason;
                    if (compilationTask.IsCompleted)
                    {
                        var response = await compilationTask.ConfigureAwait(false);

                        try
                        {
                            Log("Begin writing response.");
                            await _clientConnection.WriteBuildResponse(response, cancellationToken).ConfigureAwait(false);

                            reason = CompletionReason.Completed;
                            Log("End writing response.");
                        }
                        catch
                        {
                            reason = CompletionReason.ClientDisconnect;
                        }
                    }
                    else
                    {
                        await monitorTask.ConfigureAwait(false);

                        reason = CompletionReason.ClientDisconnect;
                    }

                    // Begin the tear down of the Task which didn't complete.
                    buildCts.Cancel();
                    return(reason);
                }
                finally
                {
                    _clientConnection.Close();

                    // Ensure that the task is completed.  If the code previously added a real result this will
                    // simply be a nop.
                    timeoutCompletionSource.TrySetResult(null);
                }
            }
Exemple #2
0
            public async Task <ConnectionData> ServeConnection(CancellationToken cancellationToken = default(CancellationToken))
            {
                try
                {
                    BuildRequest request;
                    try
                    {
                        Log("Begin reading request.");
                        request = await _clientConnection.ReadBuildRequest(cancellationToken).ConfigureAwait(false);

                        Log("End reading request.");
                    }
                    catch (Exception e)
                    {
                        LogException(e, "Error reading build request.");
                        return(new ConnectionData(CompletionReason.CompilationNotStarted));
                    }

                    var keepAlive = CheckForNewKeepAlive(request);

                    // Kick off both the compilation and a task to monitor the pipe for closing.
                    var buildCts        = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                    var compilationTask = ServeBuildRequest(request, buildCts.Token);
                    var monitorTask     = _clientConnection.CreateMonitorDisconnectTask(buildCts.Token);
                    await Task.WhenAny(compilationTask, monitorTask).ConfigureAwait(false);

                    // Do an 'await' on the completed task, preference being compilation, to force
                    // any exceptions to be realized in this method for logging.
                    CompletionReason reason;
                    if (compilationTask.IsCompleted)
                    {
                        var response = await compilationTask.ConfigureAwait(false);

                        try
                        {
                            Log("Begin writing response.");
                            await _clientConnection.WriteBuildResponse(response, cancellationToken).ConfigureAwait(false);

                            reason = CompletionReason.Completed;
                            Log("End writing response.");
                        }
                        catch
                        {
                            reason = CompletionReason.ClientDisconnect;
                        }
                    }
                    else
                    {
                        await monitorTask.ConfigureAwait(false);

                        reason = CompletionReason.ClientDisconnect;
                    }

                    // Begin the tear down of the Task which didn't complete.
                    buildCts.Cancel();
                    return(new ConnectionData(reason, keepAlive));
                }
                finally
                {
                    _clientConnection.Close();
                }
            }