Esempio n. 1
0
        /// <summary>
        /// Cleans up any context or state that may have been built up for a given task.
        /// </summary>
        /// <param name="task">The task to clean up.</param>
        /// <remarks>
        /// For many factories, this method is a no-op.  But some factories may have built up
        /// an AppDomain as part of an individual task instance, and this is their opportunity
        /// to shutdown the AppDomain.
        /// </remarks>
        public void CleanupTask(ITask task)
        {
            ErrorUtilities.VerifyThrowArgumentNull(task, "task");
            AppDomain appDomain;

            if (_tasksAndAppDomains.TryGetValue(task, out appDomain))
            {
                _tasksAndAppDomains.Remove(task);

                if (appDomain != null)
                {
                    // Unload the AppDomain asynchronously to avoid a deadlock that can happen because
                    // AppDomain.Unload blocks for the process's one Finalizer thread to finalize all
                    // objects. Some objects are RCWs for STA COM objects and as such would need the
                    // VS main thread to be processing messages in order to finalize. But if the main thread
                    // is blocked in a non-pumping wait waiting for this build request to complete, we would
                    // deadlock. By unloading asynchronously, the AppDomain unload can block till the main
                    // thread is available, even if it isn't available until after this MSBuild Task has
                    // finished executing.
                    Task.Run(() => AppDomain.Unload(appDomain));
                }
            }

            TaskHostTask taskAsTaskHostTask = task as TaskHostTask;

            if (taskAsTaskHostTask != null)
            {
                taskAsTaskHostTask.Cleanup();
            }
            else
            {
                // It's really not necessary to do it for TaskHostTasks
                TaskLoader.RemoveAssemblyResolver();
            }
        }
        /// <summary>
        /// This is responsible for cleaning up the task after the OutOfProcTaskHostNode has gathered everything it needs from this execution
        /// For example: We will need to hold on new AppDomains created until we finish getting all outputs from the task
        /// Add any other cleanup tasks here. Any method calling ExecuteTask must remember to call CleanupTask.
        /// </summary>
        internal void CleanupTask()
        {
            if (_taskAppDomain != null)
            {
                AppDomain.Unload(_taskAppDomain);
            }

            TaskLoader.RemoveAssemblyResolver();
            _wrappedTask = null;
        }
        /// <summary>
        /// This is responsible for cleaning up the task after the OutOfProcTaskHostNode has gathered everything it needs from this execution
        /// For example: We will need to hold on new AppDomains created until we finish getting all outputs from the task
        /// Add any other cleanup tasks here. Any method calling ExecuteTask must remember to call CleanupTask.
        /// </summary>
        internal void CleanupTask()
        {
#if FEATURE_APPDOMAIN
            if (_taskAppDomain != null)
            {
                AppDomain.Unload(_taskAppDomain);
            }

            TaskLoader.RemoveAssemblyResolver();
#endif
            wrappedTask = null;
        }