/// <summary>
        /// Task runner method
        /// </summary>
        private void RunTask(object state)
        {
            _isTaskExecuting = true;
            OutOfProcTaskHostTaskResult taskResult = null;
            TaskHostConfiguration taskConfiguration = state as TaskHostConfiguration;
            IDictionary<string, TaskParameter> taskParams = taskConfiguration.TaskParameters;

            // We only really know the values of these variables for sure once we see what we received from our parent 
            // environment -- otherwise if this was a completely new build, we could lose out on expected environment 
            // variables.  
            _debugCommunications = taskConfiguration.BuildProcessEnvironment.ContainsValueAndIsEqual("MSBUILDDEBUGCOMM", "1", StringComparison.OrdinalIgnoreCase);
            _updateEnvironment = !taskConfiguration.BuildProcessEnvironment.ContainsValueAndIsEqual("MSBuildTaskHostDoNotUpdateEnvironment", "1", StringComparison.OrdinalIgnoreCase);
            _updateEnvironmentAndLog = taskConfiguration.BuildProcessEnvironment.ContainsValueAndIsEqual("MSBuildTaskHostUpdateEnvironmentAndLog", "1", StringComparison.OrdinalIgnoreCase);

            try
            {
                // Change to the startup directory
                NativeMethodsShared.SetCurrentDirectory(taskConfiguration.StartupDirectory);

                if (_updateEnvironment)
                {
                    InitializeMismatchedEnvironmentTable(taskConfiguration.BuildProcessEnvironment);
                }

                // Now set the new environment
                SetTaskHostEnvironment(taskConfiguration.BuildProcessEnvironment);

                // Set culture
                Thread.CurrentThread.CurrentCulture = taskConfiguration.Culture;
                Thread.CurrentThread.CurrentUICulture = taskConfiguration.UICulture;

                string taskName = taskConfiguration.TaskName;
                string taskLocation = taskConfiguration.TaskLocation;

                // We will not create an appdomain now because of a bug
                // As a fix, we will create the class directly without wrapping it in a domain
                _taskWrapper = new OutOfProcTaskAppDomainWrapper();

                taskResult = _taskWrapper.ExecuteTask
                (
                    this as IBuildEngine,
                    taskName,
                    taskLocation,
                    taskConfiguration.ProjectFileOfTask,
                    taskConfiguration.LineNumberOfTask,
                    taskConfiguration.ColumnNumberOfTask,
                    taskConfiguration.AppDomainSetup,
                    taskParams
                );
            }
            catch (Exception e)
            {
                if (e is ThreadAbortException)
                {
                    // This thread was aborted as part of Cancellation, we will return a failure task result
                    taskResult = new OutOfProcTaskHostTaskResult(TaskCompleteType.Failure);
                }
                else if (ExceptionHandling.IsCriticalException(e))
                {
                    throw;
                }
                else
                {
                    taskResult = new OutOfProcTaskHostTaskResult(TaskCompleteType.CrashedDuringExecution, e);
                }
            }
            finally
            {
                try
                {
                    _isTaskExecuting = false;

                    IDictionary<string, string> currentEnvironment = CommunicationsUtilities.GetEnvironmentVariables();
                    currentEnvironment = UpdateEnvironmentForMainNode(currentEnvironment);

                    if (taskResult == null)
                    {
                        taskResult = new OutOfProcTaskHostTaskResult(TaskCompleteType.Failure);
                    }

                    lock (_taskCompleteLock)
                    {
                        _taskCompletePacket = new TaskHostTaskComplete
                                                    (
                                                        taskResult,
                                                        currentEnvironment
                                                    );
                    }

                    foreach (TaskParameter param in taskParams.Values)
                    {
                        // Tell remoting to forget connections to the parameter
                        RemotingServices.Disconnect(param);
                    }

                    // Restore the original clean environment
                    CommunicationsUtilities.SetEnvironment(_savedEnvironment);
                }
                catch (Exception e)
                {
                    lock (_taskCompleteLock)
                    {
                        // Create a minimal taskCompletePacket to carry the exception so that the TaskHostTask does not hang while waiting
                        _taskCompletePacket = new TaskHostTaskComplete(new OutOfProcTaskHostTaskResult(TaskCompleteType.CrashedAfterExecution, e), null);
                    }
                }
                finally
                {
                    // Call CleanupTask to unload any domains and other necessary cleanup in the taskWrapper
                    _taskWrapper.CleanupTask();

                    // The task has now fully completed executing
                    _taskCompleteEvent.Set();
                }
            }
        }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="result">Result of the task's execution.</param>
        /// <param name="buildProcessEnvironment">The build process environment as it was at the end of the task's execution.</param>
        public TaskHostTaskComplete(OutOfProcTaskHostTaskResult result, IDictionary<string, string> buildProcessEnvironment)
        {
            ErrorUtilities.VerifyThrowInternalNull(result, "result");

            _taskResult = result.Result;
            _taskException = result.TaskException;
            _taskExceptionMessage = result.ExceptionMessage;
            _taskExceptionMessageArgs = result.ExceptionMessageArgs;

            if (result.FinalParameterValues != null)
            {
                _taskOutputParameters = new Dictionary<string, TaskParameter>(StringComparer.OrdinalIgnoreCase);
                foreach (KeyValuePair<string, object> parameter in result.FinalParameterValues)
                {
                    _taskOutputParameters[parameter.Key] = new TaskParameter(parameter.Value);
                }
            }

            if (buildProcessEnvironment != null)
            {
                _buildProcessEnvironment = buildProcessEnvironment as Dictionary<string, string>;

                if (_buildProcessEnvironment == null)
                {
                    _buildProcessEnvironment = new Dictionary<string, string>(buildProcessEnvironment);
                }
            }
        }