/// <summary> /// Initializes a new instance of the <see cref="MockAsyncServiceProvider"/> class. /// </summary> /// <param name="serviceProvider">The root of all services.</param> internal MockAsyncServiceProvider(OLE.Interop.IServiceProvider serviceProvider) { this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); this.taskSchedulerService = (IVsTaskSchedulerService)serviceProvider.QueryService(typeof(SVsTaskSchedulerService).GUID); Assumes.Present(this.taskSchedulerService); }
/// <summary> /// Executes a non-cancellable operation in the specified <see cref="VsTaskRunContext"/> and doesn't wait until it is completed /// </summary> /// <param name="serviceProvider">An instance of <see cref="IServiceProvider"/>. Required.</param> /// <param name="context">The <see cref="VsTaskRunContext"/> in which to run the operation</param> /// <param name="op">The operation to run</param> internal static void BeginTask(IServiceProvider serviceProvider, VsTaskRunContext context, Action op) { Debug.Assert(serviceProvider != null, "IServiceProvider is required"); Debug.Assert(op != null, "Action is required"); IVsTaskSchedulerService taskService = serviceProvider.GetService(typeof(SVsTaskSchedulerService)) as IVsTaskSchedulerService; IVsTaskBody body = VsTaskLibraryHelper.CreateTaskBody(op); IVsTask task = VsTaskLibraryHelper.CreateTask(taskService, context, VsTaskCreationOptions.NotCancelable, body, null); task.Start(); }
/// <summary> /// Runs <paramref name="idleWork"/> over each item in <paramref name="workQueue"/> on the UI Thread during idle time. /// This method will keep iterating through <paramref name="workQueue"/> on the same idle loop while VS remains idle. /// Once VS is no longer idle, the method will yield control and pick up where it left off on the next idle loop. /// </summary> /// <typeparam name="T">The type of the data to be processed.</typeparam> /// <param name="this">The IVsTaskSchedulerService to use when scheduling the work.</param> /// <param name="idleWork">Action to run on idle.</param> /// <param name="workQueue">Data to process on idle.</param> /// <param name="token">Cancellation token to indicate when the work is no longer needed.</param> /// <returns /// >A task representing all of the asynchronous work this method is performing. When the task is marked as completed, /// either all of the work in workQueue has been processed, or the operation was canceled. /// </returns> public static Task RunOnIdleAsync <T>(this IVsTaskSchedulerService @this, Action <T> idleWork, ConcurrentQueue <T> workQueue, CancellationToken token) { // Check for good data if (idleWork == null) { throw new ArgumentNullException(nameof(idleWork)); } if (workQueue == null) { throw new ArgumentNullException(nameof(workQueue)); } return(@this.RunOnIdleAsync(idleWork, workQueue.TryDequeue, token)); }
/// <summary> /// Creates a <see cref="IVsTask"/> in the specified <see cref="VsTaskRunContext"/> /// </summary> /// <param name="serviceProvider">An instance of <see cref="IServiceProvider"/>. Required.</param> /// <param name="context">The <see cref="VsTaskRunContext"/> in which to run the operation</param> /// <param name="op">The operation to run</param> /// <param name="token">Option cancellation token <see cref="CancellationToken"/></param> /// <returns>An await-able object that returns a result</returns> private static IVsTask CreateTask <T>(IServiceProvider serviceProvider, VsTaskRunContext context, Func <T> op, CancellationToken token) { Debug.Assert(serviceProvider != null, "IServiceProvider is required"); Debug.Assert(op != null, "op is required"); IVsTaskSchedulerService taskService = serviceProvider.GetService(typeof(SVsTaskSchedulerService)) as IVsTaskSchedulerService; IVsTaskBody body = VsTaskLibraryHelper.CreateTaskBody(() => (object)op()); IVsTask task = VsTaskLibraryHelper.CreateTask(taskService, context, body); if (token != CancellationToken.None) { task.ApplyCancellationToken(token); } return(task); }
/// <summary> /// Runs <paramref name="idleWork"/> over each item in <paramref name="workData"/> on the UI Thread during idle time. /// This method will keep iterating through <paramref name="workData"/> on the same idle loop while VS remains idle. /// Once VS is no longer idle, the method will yield control and pick up where it left off on the next idle loop. /// </summary> /// <typeparam name="T">The type of the data to be processed.</typeparam> /// <param name="this">The IVsTaskSchedulerService to use when scheduling the work.</param> /// <param name="idleWork">Action to run on idle.</param> /// <param name="workData">Data to process on idle.</param> /// <param name="token">Cancellation token to indicate when the work is no longer needed.</param> /// <returns /// >A task representing all of the asynchronous work this method is performing. When the task is marked as completed, /// either all of the work in workData has been processed, or the operation was canceled. /// </returns> public static Task RunOnIdleAsync <T>(this IVsTaskSchedulerService @this, Action <T> idleWork, IEnumerable <T> workData, CancellationToken token) { // Check for good data if (idleWork == null) { throw new ArgumentNullException(nameof(idleWork)); } if (workData == null) { throw new ArgumentNullException(nameof(workData)); } // Make a copy of the items since we're going to be iterating over them across multiple dispatcher operations. T[] items = workData.ToArray(); var adapter = new TryGetNextItemEnumerableAdapter <T>(items); return(@this.RunOnIdleAsync(idleWork, adapter.TryGetNextItem, token)); }
/// <summary> /// Runs <paramref name="idleWork"/> over each item returned from <paramref name="tryGetNextItem"/> on the UI Thread during idle time. /// This method will keep processing data from <paramref name="tryGetNextItem" /> on the same idle loop while VS remains idle. /// Once VS is no longer idle, the method will yield control and pick up where it left off on the next idle loop. /// </summary> /// <typeparam name="T">The type of the data to be processed.</typeparam> /// <param name="this">The IVsTaskSchedulerService to use when scheduling the work.</param> /// <param name="idleWork">Action to run on idle.</param> /// <param name="tryGetNextItem">Delegate used to get the next piece of data to process. tryGetNextItem should return true /// when another item is available and false when there is no more data to process.</param> /// <param name="token">Cancellation token to indicate when the work is no longer needed.</param> /// <returns> /// >A task representing all of the asynchronous work this method is performing. When the task is marked as completed, /// either all of the work received from tryGetNextItem has been processed, or the operation was canceled. /// </returns> public static async Task RunOnIdleAsync <T>(this IVsTaskSchedulerService @this, Action <T> idleWork, TryGetNextItem <T> tryGetNextItem, CancellationToken token) { // Check for good data if (idleWork == null) { throw new ArgumentNullException(nameof(idleWork)); } if (tryGetNextItem == null) { throw new ArgumentNullException(nameof(tryGetNextItem)); } Stopwatch stopwatch = new Stopwatch(); T data; while (tryGetNextItem(out data)) { token.ThrowIfCancellationRequested(); await VsTaskLibraryHelper.CreateAndStartTask( @this, VsTaskRunContext.UIThreadIdlePriority, VsTaskLibraryHelper.CreateTaskBody(() => { stopwatch.Start(); do { // Ensure cancellation occurring between work items is respected token.ThrowIfCancellationRequested(); idleWork(data); }while (stopwatch.ElapsedMilliseconds < MaxMillisecondIdleTime && tryGetNextItem(out data)); stopwatch.Stop(); })); stopwatch.Reset(); } }
/// <summary> /// Runs <paramref name="idleWork"/> over each item in <paramref name="workData"/> on the UI Thread during idle time. /// This method will keep iterating through <paramref name="workData"/> on the same idle loop while VS remains idle. /// Once VS is no longer idle, the method will yield control and pick up where it left off on the next idle loop. /// </summary> /// <typeparam name="T">The type of the data to be processed.</typeparam> /// <param name="this">The IVsTaskSchedulerService to use when scheduling the work.</param> /// <param name="idleWork">Action to run on idle.</param> /// <param name="workData">Data to process on idle.</param> /// <returns /// >A task representing all of the asynchronous work this method is performing. When the task is marked as completed, /// either all of the work in workData has been processed, or the operation was canceled. /// </returns> public static Task RunOnIdleAsync <T>(this IVsTaskSchedulerService @this, Action <T> idleWork, IEnumerable <T> workData) { return(@this.RunOnIdleAsync <T>(idleWork, workData, CancellationToken.None)); }
/// <summary> /// Runs <paramref name="idleWork"/> over each item returned from <paramref name="tryGetNextItem"/> on the UI Thread during idle time. /// This method will keep processing data from <paramref name="tryGetNextItem" /> on the same idle loop while VS remains idle. /// Once VS is no longer idle, the method will yield control and pick up where it left off on the next idle loop. /// </summary> /// <typeparam name="T">The type of the data to be processed.</typeparam> /// <param name="this">The IVsTaskSchedulerService to use when scheduling the work.</param> /// <param name="idleWork">Action to run on idle.</param> /// <param name="tryGetNextItem">Delegate used to get the next piece of data to process. tryGetNextItem should return true /// when another item is available and false when there is no more data to process.</param> /// <returns> /// >A task representing all of the asynchronous work this method is performing. When the task is marked as completed, /// either all of the work received from tryGetNextItem has been processed, or the operation was canceled. /// </returns> public static Task RunOnIdleAsync <T>(this IVsTaskSchedulerService @this, Action <T> idleWork, TryGetNextItem <T> tryGetNextItem) { return(@this.RunOnIdleAsync <T>(idleWork, tryGetNextItem, CancellationToken.None)); }
/// <summary> /// Runs <paramref name="idleWork"/> over each item in <paramref name="workQueue"/> on the UI Thread during idle time. /// This method will keep iterating through <paramref name="workQueue"/> on the same idle loop while VS remains idle. /// Once VS is no longer idle, the method will yield control and pick up where it left off on the next idle loop. /// </summary> /// <typeparam name="T">The type of the data to be processed.</typeparam> /// <param name="this">The IVsTaskSchedulerService to use when scheduling the work.</param> /// <param name="idleWork">Action to run on idle.</param> /// <param name="workQueue">Data to process on idle.</param> /// <returns /// >A task representing all of the asynchronous work this method is performing. When the task is marked as completed, /// either all of the work in workQueue has been processed, or the operation was canceled. /// </returns> public static Task RunOnIdleAsync <T>(this IVsTaskSchedulerService @this, Action <T> idleWork, ConcurrentQueue <T> workQueue) { return(@this.RunOnIdleAsync <T>(idleWork, workQueue, CancellationToken.None)); }
static ProjectFactory() { ThreadHelper.ThrowIfNotOnUIThread(); taskSchedulerService = Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SVsTaskSchedulerService)) as IVsTaskSchedulerService; }